xref: /dpdk/drivers/net/ionic/ionic_main.c (revision 75f9690223b5ebd6b171ae09746ae23bc8d221d6)
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 
5e40303ebSSunil Kumar Kori #include <stdbool.h>
6e40303ebSSunil Kumar Kori 
723bf4ddbSAlfredo Cardigliano #include <rte_memzone.h>
823bf4ddbSAlfredo Cardigliano 
95ef51809SAlfredo Cardigliano #include "ionic.h"
1001a6c311SAlfredo Cardigliano #include "ionic_ethdev.h"
1101a6c311SAlfredo Cardigliano #include "ionic_lif.h"
1201a6c311SAlfredo Cardigliano 
1301a6c311SAlfredo Cardigliano static const char *
1401a6c311SAlfredo Cardigliano ionic_error_to_str(enum ionic_status_code code)
1501a6c311SAlfredo Cardigliano {
1601a6c311SAlfredo Cardigliano 	switch (code) {
1701a6c311SAlfredo Cardigliano 	case IONIC_RC_SUCCESS:
1801a6c311SAlfredo Cardigliano 		return "IONIC_RC_SUCCESS";
1901a6c311SAlfredo Cardigliano 	case IONIC_RC_EVERSION:
2001a6c311SAlfredo Cardigliano 		return "IONIC_RC_EVERSION";
2101a6c311SAlfredo Cardigliano 	case IONIC_RC_EOPCODE:
2201a6c311SAlfredo Cardigliano 		return "IONIC_RC_EOPCODE";
2301a6c311SAlfredo Cardigliano 	case IONIC_RC_EIO:
2401a6c311SAlfredo Cardigliano 		return "IONIC_RC_EIO";
2501a6c311SAlfredo Cardigliano 	case IONIC_RC_EPERM:
2601a6c311SAlfredo Cardigliano 		return "IONIC_RC_EPERM";
2701a6c311SAlfredo Cardigliano 	case IONIC_RC_EQID:
2801a6c311SAlfredo Cardigliano 		return "IONIC_RC_EQID";
2901a6c311SAlfredo Cardigliano 	case IONIC_RC_EQTYPE:
3001a6c311SAlfredo Cardigliano 		return "IONIC_RC_EQTYPE";
3101a6c311SAlfredo Cardigliano 	case IONIC_RC_ENOENT:
3201a6c311SAlfredo Cardigliano 		return "IONIC_RC_ENOENT";
3301a6c311SAlfredo Cardigliano 	case IONIC_RC_EINTR:
3401a6c311SAlfredo Cardigliano 		return "IONIC_RC_EINTR";
3501a6c311SAlfredo Cardigliano 	case IONIC_RC_EAGAIN:
3601a6c311SAlfredo Cardigliano 		return "IONIC_RC_EAGAIN";
3701a6c311SAlfredo Cardigliano 	case IONIC_RC_ENOMEM:
3801a6c311SAlfredo Cardigliano 		return "IONIC_RC_ENOMEM";
3901a6c311SAlfredo Cardigliano 	case IONIC_RC_EFAULT:
4001a6c311SAlfredo Cardigliano 		return "IONIC_RC_EFAULT";
4101a6c311SAlfredo Cardigliano 	case IONIC_RC_EBUSY:
4201a6c311SAlfredo Cardigliano 		return "IONIC_RC_EBUSY";
4301a6c311SAlfredo Cardigliano 	case IONIC_RC_EEXIST:
4401a6c311SAlfredo Cardigliano 		return "IONIC_RC_EEXIST";
4501a6c311SAlfredo Cardigliano 	case IONIC_RC_EINVAL:
4601a6c311SAlfredo Cardigliano 		return "IONIC_RC_EINVAL";
4701a6c311SAlfredo Cardigliano 	case IONIC_RC_ENOSPC:
4801a6c311SAlfredo Cardigliano 		return "IONIC_RC_ENOSPC";
4901a6c311SAlfredo Cardigliano 	case IONIC_RC_ERANGE:
5001a6c311SAlfredo Cardigliano 		return "IONIC_RC_ERANGE";
5101a6c311SAlfredo Cardigliano 	case IONIC_RC_BAD_ADDR:
5201a6c311SAlfredo Cardigliano 		return "IONIC_RC_BAD_ADDR";
5301a6c311SAlfredo Cardigliano 	case IONIC_RC_DEV_CMD:
5401a6c311SAlfredo Cardigliano 		return "IONIC_RC_DEV_CMD";
5501a6c311SAlfredo Cardigliano 	case IONIC_RC_ERROR:
5601a6c311SAlfredo Cardigliano 		return "IONIC_RC_ERROR";
5701a6c311SAlfredo Cardigliano 	case IONIC_RC_ERDMA:
5801a6c311SAlfredo Cardigliano 		return "IONIC_RC_ERDMA";
5901a6c311SAlfredo Cardigliano 	default:
6001a6c311SAlfredo Cardigliano 		return "IONIC_RC_UNKNOWN";
6101a6c311SAlfredo Cardigliano 	}
6201a6c311SAlfredo Cardigliano }
6301a6c311SAlfredo Cardigliano 
6401a6c311SAlfredo Cardigliano static const char *
6501a6c311SAlfredo Cardigliano ionic_opcode_to_str(enum ionic_cmd_opcode opcode)
6601a6c311SAlfredo Cardigliano {
6701a6c311SAlfredo Cardigliano 	switch (opcode) {
6801a6c311SAlfredo Cardigliano 	case IONIC_CMD_NOP:
6901a6c311SAlfredo Cardigliano 		return "IONIC_CMD_NOP";
7001a6c311SAlfredo Cardigliano 	case IONIC_CMD_INIT:
7101a6c311SAlfredo Cardigliano 		return "IONIC_CMD_INIT";
7201a6c311SAlfredo Cardigliano 	case IONIC_CMD_RESET:
7301a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RESET";
7401a6c311SAlfredo Cardigliano 	case IONIC_CMD_IDENTIFY:
7501a6c311SAlfredo Cardigliano 		return "IONIC_CMD_IDENTIFY";
7601a6c311SAlfredo Cardigliano 	case IONIC_CMD_GETATTR:
7701a6c311SAlfredo Cardigliano 		return "IONIC_CMD_GETATTR";
7801a6c311SAlfredo Cardigliano 	case IONIC_CMD_SETATTR:
7901a6c311SAlfredo Cardigliano 		return "IONIC_CMD_SETATTR";
8001a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_IDENTIFY:
8101a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_IDENTIFY";
8201a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_INIT:
8301a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_INIT";
8401a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_RESET:
8501a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_RESET";
8601a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_GETATTR:
8701a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_GETATTR";
8801a6c311SAlfredo Cardigliano 	case IONIC_CMD_PORT_SETATTR:
8901a6c311SAlfredo Cardigliano 		return "IONIC_CMD_PORT_SETATTR";
9001a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_INIT:
9101a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_INIT";
9201a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_RESET:
9301a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_RESET";
9401a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_IDENTIFY:
9501a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_IDENTIFY";
9601a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_SETATTR:
9701a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_SETATTR";
9801a6c311SAlfredo Cardigliano 	case IONIC_CMD_LIF_GETATTR:
9901a6c311SAlfredo Cardigliano 		return "IONIC_CMD_LIF_GETATTR";
10001a6c311SAlfredo Cardigliano 	case IONIC_CMD_RX_MODE_SET:
10101a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RX_MODE_SET";
10201a6c311SAlfredo Cardigliano 	case IONIC_CMD_RX_FILTER_ADD:
10301a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RX_FILTER_ADD";
10401a6c311SAlfredo Cardigliano 	case IONIC_CMD_RX_FILTER_DEL:
10501a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RX_FILTER_DEL";
10601a6c311SAlfredo Cardigliano 	case IONIC_CMD_Q_INIT:
10701a6c311SAlfredo Cardigliano 		return "IONIC_CMD_Q_INIT";
10801a6c311SAlfredo Cardigliano 	case IONIC_CMD_Q_CONTROL:
10901a6c311SAlfredo Cardigliano 		return "IONIC_CMD_Q_CONTROL";
11001a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_RESET_LIF:
11101a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_RESET_LIF";
11201a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_CREATE_EQ:
11301a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_CREATE_EQ";
11401a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_CREATE_CQ:
11501a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_CREATE_CQ";
11601a6c311SAlfredo Cardigliano 	case IONIC_CMD_RDMA_CREATE_ADMINQ:
11701a6c311SAlfredo Cardigliano 		return "IONIC_CMD_RDMA_CREATE_ADMINQ";
11801a6c311SAlfredo Cardigliano 	default:
11901a6c311SAlfredo Cardigliano 		return "DEVCMD_UNKNOWN";
12001a6c311SAlfredo Cardigliano 	}
12101a6c311SAlfredo Cardigliano }
12201a6c311SAlfredo Cardigliano 
12301a6c311SAlfredo Cardigliano int
12401a6c311SAlfredo Cardigliano ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout)
12501a6c311SAlfredo Cardigliano {
12601a6c311SAlfredo Cardigliano 	const char *name;
12701a6c311SAlfredo Cardigliano 	const char *status;
12801a6c311SAlfredo Cardigliano 
12901a6c311SAlfredo Cardigliano 	if (ctx->comp.comp.status || timeout) {
13001a6c311SAlfredo Cardigliano 		name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
13101a6c311SAlfredo Cardigliano 		status = ionic_error_to_str(ctx->comp.comp.status);
13201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "%s (%d) failed: %s (%d)",
13301a6c311SAlfredo Cardigliano 			name,
13401a6c311SAlfredo Cardigliano 			ctx->cmd.cmd.opcode,
13501a6c311SAlfredo Cardigliano 			timeout ? "TIMEOUT" : status,
13601a6c311SAlfredo Cardigliano 			timeout ? -1 : ctx->comp.comp.status);
13701a6c311SAlfredo Cardigliano 		return -EIO;
13801a6c311SAlfredo Cardigliano 	}
13901a6c311SAlfredo Cardigliano 
14001a6c311SAlfredo Cardigliano 	return 0;
14101a6c311SAlfredo Cardigliano }
14201a6c311SAlfredo Cardigliano 
14301a6c311SAlfredo Cardigliano static int
14401a6c311SAlfredo Cardigliano ionic_wait_ctx_for_completion(struct ionic_lif *lif, struct ionic_qcq *qcq,
14501a6c311SAlfredo Cardigliano 		struct ionic_admin_ctx *ctx, unsigned long max_wait)
14601a6c311SAlfredo Cardigliano {
14747dc2bd3SAndrew Boyer 	unsigned long step_usec = IONIC_DEVCMD_CHECK_PERIOD_US;
14847dc2bd3SAndrew Boyer 	unsigned long max_wait_usec = max_wait * 1000000L;
14947dc2bd3SAndrew Boyer 	unsigned long elapsed_usec = 0;
15001a6c311SAlfredo Cardigliano 	int budget = 8;
15101a6c311SAlfredo Cardigliano 
15247dc2bd3SAndrew Boyer 	while (ctx->pending_work && elapsed_usec < max_wait_usec) {
15301a6c311SAlfredo Cardigliano 		/*
15401a6c311SAlfredo Cardigliano 		 * Locking here as adminq is served inline (this could be called
15501a6c311SAlfredo Cardigliano 		 * from multiple places)
15601a6c311SAlfredo Cardigliano 		 */
15701a6c311SAlfredo Cardigliano 		rte_spinlock_lock(&lif->adminq_service_lock);
15801a6c311SAlfredo Cardigliano 
15901a6c311SAlfredo Cardigliano 		ionic_qcq_service(qcq, budget, ionic_adminq_service, NULL);
16001a6c311SAlfredo Cardigliano 
16101a6c311SAlfredo Cardigliano 		rte_spinlock_unlock(&lif->adminq_service_lock);
16201a6c311SAlfredo Cardigliano 
16347dc2bd3SAndrew Boyer 		rte_delay_us_block(step_usec);
16447dc2bd3SAndrew Boyer 		elapsed_usec += step_usec;
16501a6c311SAlfredo Cardigliano 	}
16601a6c311SAlfredo Cardigliano 
16701a6c311SAlfredo Cardigliano 	return (!ctx->pending_work);
16801a6c311SAlfredo Cardigliano }
16901a6c311SAlfredo Cardigliano 
17001a6c311SAlfredo Cardigliano int
17101a6c311SAlfredo Cardigliano ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
17201a6c311SAlfredo Cardigliano {
17301a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
17401a6c311SAlfredo Cardigliano 	bool done;
17501a6c311SAlfredo Cardigliano 	int err;
17601a6c311SAlfredo Cardigliano 
17701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Sending %s to the admin queue",
17801a6c311SAlfredo Cardigliano 		ionic_opcode_to_str(ctx->cmd.cmd.opcode));
17901a6c311SAlfredo Cardigliano 
18001a6c311SAlfredo Cardigliano 	err = ionic_adminq_post(lif, ctx);
18101a6c311SAlfredo Cardigliano 	if (err) {
18201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure posting to the admin queue %d (%d)",
18301a6c311SAlfredo Cardigliano 			ctx->cmd.cmd.opcode, err);
18401a6c311SAlfredo Cardigliano 
18501a6c311SAlfredo Cardigliano 		return err;
18601a6c311SAlfredo Cardigliano 	}
18701a6c311SAlfredo Cardigliano 
18801a6c311SAlfredo Cardigliano 	done = ionic_wait_ctx_for_completion(lif, qcq, ctx,
18901a6c311SAlfredo Cardigliano 		IONIC_DEVCMD_TIMEOUT);
19001a6c311SAlfredo Cardigliano 
191*75f96902SAndrew Boyer 	return ionic_adminq_check_err(ctx, !done /* timed out */);
19201a6c311SAlfredo Cardigliano }
1935ef51809SAlfredo Cardigliano 
1945ef51809SAlfredo Cardigliano static int
1955ef51809SAlfredo Cardigliano ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)
1965ef51809SAlfredo Cardigliano {
19747dc2bd3SAndrew Boyer 	unsigned long step_usec = IONIC_DEVCMD_CHECK_PERIOD_US;
19847dc2bd3SAndrew Boyer 	unsigned long max_wait_usec = max_wait * 1000000L;
19947dc2bd3SAndrew Boyer 	unsigned long elapsed_usec = 0;
2005ef51809SAlfredo Cardigliano 	int done;
2015ef51809SAlfredo Cardigliano 
2025ef51809SAlfredo Cardigliano 	/* Wait for dev cmd to complete.. but no more than max_wait sec */
2035ef51809SAlfredo Cardigliano 
2045ef51809SAlfredo Cardigliano 	do {
2055ef51809SAlfredo Cardigliano 		done = ionic_dev_cmd_done(idev);
2065ef51809SAlfredo Cardigliano 		if (done) {
20747dc2bd3SAndrew Boyer 			IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld usecs",
20847dc2bd3SAndrew Boyer 				ioread8(&idev->dev_cmd->cmd.cmd.opcode),
20947dc2bd3SAndrew Boyer 				elapsed_usec);
2105ef51809SAlfredo Cardigliano 			return 0;
2115ef51809SAlfredo Cardigliano 		}
2125ef51809SAlfredo Cardigliano 
21347dc2bd3SAndrew Boyer 		rte_delay_us_block(step_usec);
2145ef51809SAlfredo Cardigliano 
21547dc2bd3SAndrew Boyer 		elapsed_usec += step_usec;
21647dc2bd3SAndrew Boyer 	} while (elapsed_usec < max_wait_usec);
2175ef51809SAlfredo Cardigliano 
21847dc2bd3SAndrew Boyer 	IONIC_PRINT(ERR, "DEVCMD %d timeout after %ld usecs",
21947dc2bd3SAndrew Boyer 		ioread8(&idev->dev_cmd->cmd.cmd.opcode),
22047dc2bd3SAndrew Boyer 		elapsed_usec);
2215ef51809SAlfredo Cardigliano 
2225ef51809SAlfredo Cardigliano 	return -ETIMEDOUT;
2235ef51809SAlfredo Cardigliano }
2245ef51809SAlfredo Cardigliano 
2255ef51809SAlfredo Cardigliano static int
2265ef51809SAlfredo Cardigliano ionic_dev_cmd_check_error(struct ionic_dev *idev)
2275ef51809SAlfredo Cardigliano {
2285ef51809SAlfredo Cardigliano 	uint8_t status;
2295ef51809SAlfredo Cardigliano 
2305ef51809SAlfredo Cardigliano 	status = ionic_dev_cmd_status(idev);
2315ef51809SAlfredo Cardigliano 	if (status == 0)
2325ef51809SAlfredo Cardigliano 		return 0;
2335ef51809SAlfredo Cardigliano 
2345ef51809SAlfredo Cardigliano 	return -EIO;
2355ef51809SAlfredo Cardigliano }
2365ef51809SAlfredo Cardigliano 
2375ef51809SAlfredo Cardigliano int
2385ef51809SAlfredo Cardigliano ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait)
2395ef51809SAlfredo Cardigliano {
2405ef51809SAlfredo Cardigliano 	int err;
2415ef51809SAlfredo Cardigliano 
2425ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait(idev, max_wait);
2435ef51809SAlfredo Cardigliano 
244*75f96902SAndrew Boyer 	if (!err)
245*75f96902SAndrew Boyer 		err = ionic_dev_cmd_check_error(idev);
246*75f96902SAndrew Boyer 
247*75f96902SAndrew Boyer 	return err;
2485ef51809SAlfredo Cardigliano }
2495ef51809SAlfredo Cardigliano 
2505ef51809SAlfredo Cardigliano int
2515ef51809SAlfredo Cardigliano ionic_setup(struct ionic_adapter *adapter)
2525ef51809SAlfredo Cardigliano {
2535ef51809SAlfredo Cardigliano 	return ionic_dev_setup(adapter);
2545ef51809SAlfredo Cardigliano }
2555ef51809SAlfredo Cardigliano 
2565ef51809SAlfredo Cardigliano int
2575ef51809SAlfredo Cardigliano ionic_identify(struct ionic_adapter *adapter)
2585ef51809SAlfredo Cardigliano {
2595ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
2605ef51809SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
2615ef51809SAlfredo Cardigliano 	int err = 0;
2625ef51809SAlfredo Cardigliano 	uint32_t i;
2635ef51809SAlfredo Cardigliano 	unsigned int nwords;
2645ef51809SAlfredo Cardigliano 	uint32_t drv_size = sizeof(ident->drv.words) /
2655ef51809SAlfredo Cardigliano 		sizeof(ident->drv.words[0]);
2665ef51809SAlfredo Cardigliano 	uint32_t cmd_size = sizeof(idev->dev_cmd->data) /
2675ef51809SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
2685ef51809SAlfredo Cardigliano 	uint32_t dev_size = sizeof(ident->dev.words) /
2695ef51809SAlfredo Cardigliano 		sizeof(ident->dev.words[0]);
2705ef51809SAlfredo Cardigliano 
2715ef51809SAlfredo Cardigliano 	memset(ident, 0, sizeof(*ident));
2725ef51809SAlfredo Cardigliano 
2735ef51809SAlfredo Cardigliano 	ident->drv.os_type = IONIC_OS_TYPE_LINUX;
2745ef51809SAlfredo Cardigliano 	ident->drv.os_dist = 0;
2755ef51809SAlfredo Cardigliano 	snprintf(ident->drv.os_dist_str,
2765ef51809SAlfredo Cardigliano 		sizeof(ident->drv.os_dist_str), "Unknown");
2775ef51809SAlfredo Cardigliano 	ident->drv.kernel_ver = 0;
2785ef51809SAlfredo Cardigliano 	snprintf(ident->drv.kernel_ver_str,
2795ef51809SAlfredo Cardigliano 		sizeof(ident->drv.kernel_ver_str), "DPDK");
2805ef51809SAlfredo Cardigliano 	strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION,
2815ef51809SAlfredo Cardigliano 		sizeof(ident->drv.driver_ver_str) - 1);
2825ef51809SAlfredo Cardigliano 
2835ef51809SAlfredo Cardigliano 	nwords = RTE_MIN(drv_size, cmd_size);
2845ef51809SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
2855ef51809SAlfredo Cardigliano 		iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]);
2865ef51809SAlfredo Cardigliano 
2875ef51809SAlfredo Cardigliano 	ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1);
2885ef51809SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
2895ef51809SAlfredo Cardigliano 	if (!err) {
2905ef51809SAlfredo Cardigliano 		nwords = RTE_MIN(dev_size, cmd_size);
2915ef51809SAlfredo Cardigliano 		for (i = 0; i < nwords; i++)
2925ef51809SAlfredo Cardigliano 			ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]);
2935ef51809SAlfredo Cardigliano 	}
2945ef51809SAlfredo Cardigliano 
2955ef51809SAlfredo Cardigliano 	return err;
2965ef51809SAlfredo Cardigliano }
2975ef51809SAlfredo Cardigliano 
2985ef51809SAlfredo Cardigliano int
2995ef51809SAlfredo Cardigliano ionic_init(struct ionic_adapter *adapter)
3005ef51809SAlfredo Cardigliano {
3015ef51809SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
3025ef51809SAlfredo Cardigliano 
3035ef51809SAlfredo Cardigliano 	ionic_dev_cmd_init(idev);
304*75f96902SAndrew Boyer 	return ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
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 
3125ef51809SAlfredo Cardigliano 	ionic_dev_cmd_reset(idev);
313*75f96902SAndrew Boyer 	return ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
3145ef51809SAlfredo Cardigliano }
31523bf4ddbSAlfredo Cardigliano 
31623bf4ddbSAlfredo Cardigliano int
31723bf4ddbSAlfredo Cardigliano ionic_port_identify(struct ionic_adapter *adapter)
31823bf4ddbSAlfredo Cardigliano {
31923bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
32023bf4ddbSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
32123bf4ddbSAlfredo Cardigliano 	unsigned int port_words = sizeof(ident->port.words) /
32223bf4ddbSAlfredo Cardigliano 		sizeof(ident->port.words[0]);
32323bf4ddbSAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
32423bf4ddbSAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
32523bf4ddbSAlfredo Cardigliano 	unsigned int i;
32623bf4ddbSAlfredo Cardigliano 	unsigned int nwords;
32723bf4ddbSAlfredo Cardigliano 	int err;
32823bf4ddbSAlfredo Cardigliano 
32923bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_identify(idev);
33023bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
33123bf4ddbSAlfredo Cardigliano 	if (!err) {
33223bf4ddbSAlfredo Cardigliano 		nwords = RTE_MIN(port_words, cmd_words);
33323bf4ddbSAlfredo Cardigliano 		for (i = 0; i < nwords; i++)
33423bf4ddbSAlfredo Cardigliano 			ident->port.words[i] =
33523bf4ddbSAlfredo Cardigliano 				ioread32(&idev->dev_cmd->data[i]);
33623bf4ddbSAlfredo Cardigliano 	}
33723bf4ddbSAlfredo Cardigliano 
33823bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed);
33923bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu);
34023bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "state %d ", ident->port.config.state);
34123bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable);
34223bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type);
34323bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type);
34423bf4ddbSAlfredo Cardigliano 	IONIC_PRINT(INFO, "loopback_mode %d",
34523bf4ddbSAlfredo Cardigliano 		ident->port.config.loopback_mode);
34623bf4ddbSAlfredo Cardigliano 
34723bf4ddbSAlfredo Cardigliano 	return err;
34823bf4ddbSAlfredo Cardigliano }
34923bf4ddbSAlfredo Cardigliano 
35023bf4ddbSAlfredo Cardigliano static const struct rte_memzone *
35123bf4ddbSAlfredo Cardigliano ionic_memzone_reserve(const char *name, uint32_t len, int socket_id)
35223bf4ddbSAlfredo Cardigliano {
35323bf4ddbSAlfredo Cardigliano 	const struct rte_memzone *mz;
35423bf4ddbSAlfredo Cardigliano 
35523bf4ddbSAlfredo Cardigliano 	mz = rte_memzone_lookup(name);
35623bf4ddbSAlfredo Cardigliano 	if (mz)
35723bf4ddbSAlfredo Cardigliano 		return mz;
35823bf4ddbSAlfredo Cardigliano 
35923bf4ddbSAlfredo Cardigliano 	mz = rte_memzone_reserve_aligned(name, len, socket_id,
36023bf4ddbSAlfredo Cardigliano 		RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN);
36123bf4ddbSAlfredo Cardigliano 	return mz;
36223bf4ddbSAlfredo Cardigliano }
36323bf4ddbSAlfredo Cardigliano 
36423bf4ddbSAlfredo Cardigliano int
36523bf4ddbSAlfredo Cardigliano ionic_port_init(struct ionic_adapter *adapter)
36623bf4ddbSAlfredo Cardigliano {
36723bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
36823bf4ddbSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
36923bf4ddbSAlfredo Cardigliano 	char z_name[RTE_MEMZONE_NAMESIZE];
37023bf4ddbSAlfredo Cardigliano 	unsigned int config_words = sizeof(ident->port.config.words) /
37123bf4ddbSAlfredo Cardigliano 		sizeof(ident->port.config.words[0]);
37223bf4ddbSAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
37323bf4ddbSAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
37423bf4ddbSAlfredo Cardigliano 	unsigned int nwords;
37523bf4ddbSAlfredo Cardigliano 	unsigned int i;
37623bf4ddbSAlfredo Cardigliano 	int err;
37723bf4ddbSAlfredo Cardigliano 
37823bf4ddbSAlfredo Cardigliano 	if (idev->port_info)
37923bf4ddbSAlfredo Cardigliano 		return 0;
38023bf4ddbSAlfredo Cardigliano 
38123bf4ddbSAlfredo Cardigliano 	idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE);
38223bf4ddbSAlfredo Cardigliano 
38323bf4ddbSAlfredo Cardigliano 	snprintf(z_name, sizeof(z_name), "%s_port_%s_info",
38423bf4ddbSAlfredo Cardigliano 		IONIC_DRV_NAME,
38523bf4ddbSAlfredo Cardigliano 		adapter->pci_dev->device.name);
38623bf4ddbSAlfredo Cardigliano 
38723bf4ddbSAlfredo Cardigliano 	idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz,
38823bf4ddbSAlfredo Cardigliano 		SOCKET_ID_ANY);
38923bf4ddbSAlfredo Cardigliano 	if (!idev->port_info_z) {
39023bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve port info DMA memory");
39123bf4ddbSAlfredo Cardigliano 		return -ENOMEM;
39223bf4ddbSAlfredo Cardigliano 	}
39323bf4ddbSAlfredo Cardigliano 
39423bf4ddbSAlfredo Cardigliano 	idev->port_info = idev->port_info_z->addr;
39523bf4ddbSAlfredo Cardigliano 	idev->port_info_pa = idev->port_info_z->iova;
39623bf4ddbSAlfredo Cardigliano 
39723bf4ddbSAlfredo Cardigliano 	nwords = RTE_MIN(config_words, cmd_words);
39823bf4ddbSAlfredo Cardigliano 
39923bf4ddbSAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
40023bf4ddbSAlfredo Cardigliano 		iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]);
40123bf4ddbSAlfredo Cardigliano 
40223bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_init(idev);
40323bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
40423bf4ddbSAlfredo Cardigliano 	if (err) {
40523bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to init port");
40623bf4ddbSAlfredo Cardigliano 		return err;
40723bf4ddbSAlfredo Cardigliano 	}
40823bf4ddbSAlfredo Cardigliano 
40923bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
41023bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
41123bf4ddbSAlfredo Cardigliano 	if (err) {
41223bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port UP");
41323bf4ddbSAlfredo Cardigliano 		return err;
41423bf4ddbSAlfredo Cardigliano 	}
41523bf4ddbSAlfredo Cardigliano 
41623bf4ddbSAlfredo Cardigliano 	return 0;
41723bf4ddbSAlfredo Cardigliano }
41823bf4ddbSAlfredo Cardigliano 
41923bf4ddbSAlfredo Cardigliano int
42023bf4ddbSAlfredo Cardigliano ionic_port_reset(struct ionic_adapter *adapter)
42123bf4ddbSAlfredo Cardigliano {
42223bf4ddbSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
42323bf4ddbSAlfredo Cardigliano 	int err;
42423bf4ddbSAlfredo Cardigliano 
42523bf4ddbSAlfredo Cardigliano 	if (!idev->port_info)
42623bf4ddbSAlfredo Cardigliano 		return 0;
42723bf4ddbSAlfredo Cardigliano 
42823bf4ddbSAlfredo Cardigliano 	ionic_dev_cmd_port_reset(idev);
42923bf4ddbSAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
43023bf4ddbSAlfredo Cardigliano 	if (err) {
43123bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to reset port");
43223bf4ddbSAlfredo Cardigliano 		return err;
43323bf4ddbSAlfredo Cardigliano 	}
43423bf4ddbSAlfredo Cardigliano 
43523bf4ddbSAlfredo Cardigliano 	idev->port_info = NULL;
43623bf4ddbSAlfredo Cardigliano 	idev->port_info_pa = 0;
43723bf4ddbSAlfredo Cardigliano 
43823bf4ddbSAlfredo Cardigliano 	return 0;
43923bf4ddbSAlfredo Cardigliano }
440