xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 27b942c89afbd61ff3d026acf69d6198b7d05c86)
1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2669c8de6SAlfredo Cardigliano  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3669c8de6SAlfredo Cardigliano  */
4669c8de6SAlfredo Cardigliano 
5669c8de6SAlfredo Cardigliano #include <rte_malloc.h>
6669c8de6SAlfredo Cardigliano #include <rte_ethdev_driver.h>
7669c8de6SAlfredo Cardigliano 
8669c8de6SAlfredo Cardigliano #include "ionic.h"
9669c8de6SAlfredo Cardigliano #include "ionic_logs.h"
10669c8de6SAlfredo Cardigliano #include "ionic_lif.h"
11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h"
12669c8de6SAlfredo Cardigliano 
1301a6c311SAlfredo Cardigliano int
1401a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq)
1501a6c311SAlfredo Cardigliano {
1601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1701a6c311SAlfredo Cardigliano 	struct ionic_lif *lif = q->lif;
1801a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1901a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
2001a6c311SAlfredo Cardigliano 		.pending_work = true,
2101a6c311SAlfredo Cardigliano 		.cmd.q_control = {
2201a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
2301a6c311SAlfredo Cardigliano 			.lif_index = lif->index,
2401a6c311SAlfredo Cardigliano 			.type = q->type,
2501a6c311SAlfredo Cardigliano 			.index = q->index,
2601a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_ENABLE,
2701a6c311SAlfredo Cardigliano 		},
2801a6c311SAlfredo Cardigliano 	};
2901a6c311SAlfredo Cardigliano 
3001a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR) {
3101a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
3201a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
3301a6c311SAlfredo Cardigliano 	}
3401a6c311SAlfredo Cardigliano 
3501a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
3601a6c311SAlfredo Cardigliano }
3701a6c311SAlfredo Cardigliano 
3801a6c311SAlfredo Cardigliano int
3901a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
4001a6c311SAlfredo Cardigliano {
4101a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
4201a6c311SAlfredo Cardigliano 	struct ionic_lif *lif = q->lif;
4301a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
4401a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
4501a6c311SAlfredo Cardigliano 		.pending_work = true,
4601a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4701a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4801a6c311SAlfredo Cardigliano 			.lif_index = lif->index,
4901a6c311SAlfredo Cardigliano 			.type = q->type,
5001a6c311SAlfredo Cardigliano 			.index = q->index,
5101a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
5201a6c311SAlfredo Cardigliano 		},
5301a6c311SAlfredo Cardigliano 	};
5401a6c311SAlfredo Cardigliano 
5501a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR) {
5601a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
5701a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
5801a6c311SAlfredo Cardigliano 	}
5901a6c311SAlfredo Cardigliano 
6001a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
6101a6c311SAlfredo Cardigliano }
6201a6c311SAlfredo Cardigliano 
6301a6c311SAlfredo Cardigliano int
6401a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
6501a6c311SAlfredo Cardigliano {
6601a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
6701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
6801a6c311SAlfredo Cardigliano 	unsigned long index;
6901a6c311SAlfredo Cardigliano 
7001a6c311SAlfredo Cardigliano 	/*
7101a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
7201a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
7301a6c311SAlfredo Cardigliano 	 * which hash index = 0)
7401a6c311SAlfredo Cardigliano 	 */
7501a6c311SAlfredo Cardigliano 
7601a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
7701a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
7801a6c311SAlfredo Cardigliano 			break;
7901a6c311SAlfredo Cardigliano 
8001a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
8101a6c311SAlfredo Cardigliano 		return -ENOSPC;
8201a6c311SAlfredo Cardigliano 
8301a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
8401a6c311SAlfredo Cardigliano 
8501a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
8601a6c311SAlfredo Cardigliano 
8701a6c311SAlfredo Cardigliano 	return 0;
8801a6c311SAlfredo Cardigliano }
8901a6c311SAlfredo Cardigliano 
9001a6c311SAlfredo Cardigliano void
9101a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
9201a6c311SAlfredo Cardigliano {
9301a6c311SAlfredo Cardigliano 	if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
9401a6c311SAlfredo Cardigliano 		lif->adapter->intrs[intr->index] = false;
9501a6c311SAlfredo Cardigliano }
9601a6c311SAlfredo Cardigliano 
9701a6c311SAlfredo Cardigliano static int
9801a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
9901a6c311SAlfredo Cardigliano 		uint32_t index,
10001a6c311SAlfredo Cardigliano 		const char *base, uint32_t flags,
10101a6c311SAlfredo Cardigliano 		uint32_t num_descs,
10201a6c311SAlfredo Cardigliano 		uint32_t desc_size,
10301a6c311SAlfredo Cardigliano 		uint32_t cq_desc_size,
10401a6c311SAlfredo Cardigliano 		uint32_t sg_desc_size,
10501a6c311SAlfredo Cardigliano 		uint32_t pid, struct ionic_qcq **qcq)
10601a6c311SAlfredo Cardigliano {
10701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
10801a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
10901a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
11001a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
11101a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
11201a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
11301a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
11401a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
11501a6c311SAlfredo Cardigliano 	int err;
11601a6c311SAlfredo Cardigliano 
11701a6c311SAlfredo Cardigliano 	*qcq = NULL;
11801a6c311SAlfredo Cardigliano 
11901a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
12001a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
12101a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
12201a6c311SAlfredo Cardigliano 
12301a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
12401a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
12501a6c311SAlfredo Cardigliano 	/*
12601a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
12701a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
12801a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
12901a6c311SAlfredo Cardigliano 	 */
13001a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
13101a6c311SAlfredo Cardigliano 
13201a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
13301a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
13401a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
13501a6c311SAlfredo Cardigliano 	}
13601a6c311SAlfredo Cardigliano 
13701a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
13801a6c311SAlfredo Cardigliano 	if (!new) {
13901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
14001a6c311SAlfredo Cardigliano 		return -ENOMEM;
14101a6c311SAlfredo Cardigliano 	}
14201a6c311SAlfredo Cardigliano 
14301a6c311SAlfredo Cardigliano 	new->lif = lif;
14401a6c311SAlfredo Cardigliano 	new->flags = flags;
14501a6c311SAlfredo Cardigliano 
14601a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
14701a6c311SAlfredo Cardigliano 	if (!new->q.info) {
14801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
14901a6c311SAlfredo Cardigliano 		return -ENOMEM;
15001a6c311SAlfredo Cardigliano 	}
15101a6c311SAlfredo Cardigliano 
15201a6c311SAlfredo Cardigliano 	new->q.type = type;
15301a6c311SAlfredo Cardigliano 
15401a6c311SAlfredo Cardigliano 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
15501a6c311SAlfredo Cardigliano 		desc_size, sg_desc_size, pid);
15601a6c311SAlfredo Cardigliano 	if (err) {
15701a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
15801a6c311SAlfredo Cardigliano 		return err;
15901a6c311SAlfredo Cardigliano 	}
16001a6c311SAlfredo Cardigliano 
16101a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR) {
16201a6c311SAlfredo Cardigliano 		err = ionic_intr_alloc(lif, &new->intr);
16301a6c311SAlfredo Cardigliano 		if (err)
16401a6c311SAlfredo Cardigliano 			return err;
16501a6c311SAlfredo Cardigliano 
16601a6c311SAlfredo Cardigliano 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
16701a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
16801a6c311SAlfredo Cardigliano 	} else {
16901a6c311SAlfredo Cardigliano 		new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
17001a6c311SAlfredo Cardigliano 	}
17101a6c311SAlfredo Cardigliano 
17201a6c311SAlfredo Cardigliano 	err = ionic_cq_init(lif, &new->cq, &new->intr,
17301a6c311SAlfredo Cardigliano 		num_descs, cq_desc_size);
17401a6c311SAlfredo Cardigliano 	if (err) {
17501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
17601a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
17701a6c311SAlfredo Cardigliano 	}
17801a6c311SAlfredo Cardigliano 
17901a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
18001a6c311SAlfredo Cardigliano 		base /* name */, index /* queue_idx */,
18101a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
18201a6c311SAlfredo Cardigliano 
18301a6c311SAlfredo Cardigliano 	if (!new->base_z) {
18401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
18501a6c311SAlfredo Cardigliano 		err = -ENOMEM;
18601a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
18701a6c311SAlfredo Cardigliano 	}
18801a6c311SAlfredo Cardigliano 
18901a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
19001a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
19101a6c311SAlfredo Cardigliano 	new->total_size = total_size;
19201a6c311SAlfredo Cardigliano 
19301a6c311SAlfredo Cardigliano 	q_base = new->base;
19401a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
19501a6c311SAlfredo Cardigliano 
19601a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
19701a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
19801a6c311SAlfredo Cardigliano 
19901a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
20001a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
20101a6c311SAlfredo Cardigliano 			PAGE_SIZE);
20201a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
20301a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
20401a6c311SAlfredo Cardigliano 	}
20501a6c311SAlfredo Cardigliano 
20601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Q-Base-PA = %ju CQ-Base-PA = %ju "
20701a6c311SAlfredo Cardigliano 		"SG-base-PA = %ju",
20801a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
20901a6c311SAlfredo Cardigliano 
21001a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
21101a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
21201a6c311SAlfredo Cardigliano 	ionic_cq_bind(&new->cq, &new->q);
21301a6c311SAlfredo Cardigliano 
21401a6c311SAlfredo Cardigliano 	*qcq = new;
21501a6c311SAlfredo Cardigliano 
21601a6c311SAlfredo Cardigliano 	return 0;
21701a6c311SAlfredo Cardigliano 
21801a6c311SAlfredo Cardigliano err_out_free_intr:
21901a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR)
22001a6c311SAlfredo Cardigliano 		ionic_intr_free(lif, &new->intr);
22101a6c311SAlfredo Cardigliano 
22201a6c311SAlfredo Cardigliano 	return err;
22301a6c311SAlfredo Cardigliano }
22401a6c311SAlfredo Cardigliano 
22501a6c311SAlfredo Cardigliano void
22601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
22701a6c311SAlfredo Cardigliano {
22801a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
22901a6c311SAlfredo Cardigliano 		qcq->base = NULL;
23001a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
23101a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
23201a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
23301a6c311SAlfredo Cardigliano 	}
23401a6c311SAlfredo Cardigliano 
23501a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
23601a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
23701a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
23801a6c311SAlfredo Cardigliano 	}
23901a6c311SAlfredo Cardigliano 
24001a6c311SAlfredo Cardigliano 	rte_free(qcq);
24101a6c311SAlfredo Cardigliano }
24201a6c311SAlfredo Cardigliano 
24301a6c311SAlfredo Cardigliano static int
24401a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
24501a6c311SAlfredo Cardigliano {
24601a6c311SAlfredo Cardigliano 	uint32_t flags;
24701a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
24801a6c311SAlfredo Cardigliano 
24901a6c311SAlfredo Cardigliano 	flags = 0;
25001a6c311SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
25101a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
25201a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
25301a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
25401a6c311SAlfredo Cardigliano 		0,
25501a6c311SAlfredo Cardigliano 		lif->kern_pid, &lif->adminqcq);
256*27b942c8SAlfredo Cardigliano 	if (err)
257*27b942c8SAlfredo Cardigliano 		return err;
25801a6c311SAlfredo Cardigliano 
259*27b942c8SAlfredo Cardigliano 	return 0;
260*27b942c8SAlfredo Cardigliano }
261*27b942c8SAlfredo Cardigliano 
262*27b942c8SAlfredo Cardigliano static int
263*27b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
264*27b942c8SAlfredo Cardigliano {
265*27b942c8SAlfredo Cardigliano 	uint32_t flags;
266*27b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
267*27b942c8SAlfredo Cardigliano 
268*27b942c8SAlfredo Cardigliano 	flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
269*27b942c8SAlfredo Cardigliano 
270*27b942c8SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
271*27b942c8SAlfredo Cardigliano 		flags,
272*27b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
273*27b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
274*27b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
275*27b942c8SAlfredo Cardigliano 		0,
276*27b942c8SAlfredo Cardigliano 		lif->kern_pid, &lif->notifyqcq);
27701a6c311SAlfredo Cardigliano 	if (err)
27801a6c311SAlfredo Cardigliano 		return err;
27901a6c311SAlfredo Cardigliano 
28001a6c311SAlfredo Cardigliano 	return 0;
28101a6c311SAlfredo Cardigliano }
28201a6c311SAlfredo Cardigliano 
283c67719e1SAlfredo Cardigliano static void *
284c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
285c67719e1SAlfredo Cardigliano {
286c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
287c67719e1SAlfredo Cardigliano 
288c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
289c67719e1SAlfredo Cardigliano 		return NULL;
290c67719e1SAlfredo Cardigliano 
291c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
292c67719e1SAlfredo Cardigliano }
293c67719e1SAlfredo Cardigliano 
294669c8de6SAlfredo Cardigliano int
295669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
296669c8de6SAlfredo Cardigliano {
297c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
298669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
299c67719e1SAlfredo Cardigliano 	int dbpage_num;
30001a6c311SAlfredo Cardigliano 	int err;
301669c8de6SAlfredo Cardigliano 
302669c8de6SAlfredo Cardigliano 	snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index);
303669c8de6SAlfredo Cardigliano 
304669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
305669c8de6SAlfredo Cardigliano 
30601a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
30701a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
30801a6c311SAlfredo Cardigliano 
309c67719e1SAlfredo Cardigliano 	lif->kern_pid = 0;
310c67719e1SAlfredo Cardigliano 
311c67719e1SAlfredo Cardigliano 	dbpage_num = ionic_db_page_num(lif, 0);
312c67719e1SAlfredo Cardigliano 
313c67719e1SAlfredo Cardigliano 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num);
314c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
315c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
316c67719e1SAlfredo Cardigliano 		return -ENOMEM;
317c67719e1SAlfredo Cardigliano 	}
318c67719e1SAlfredo Cardigliano 
319*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
320*27b942c8SAlfredo Cardigliano 
321*27b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
322*27b942c8SAlfredo Cardigliano 
323*27b942c8SAlfredo Cardigliano 	if (err) {
324*27b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
325*27b942c8SAlfredo Cardigliano 		return err;
326*27b942c8SAlfredo Cardigliano 	}
327*27b942c8SAlfredo Cardigliano 
328*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
329*27b942c8SAlfredo Cardigliano 
33001a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
33101a6c311SAlfredo Cardigliano 
33201a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
33301a6c311SAlfredo Cardigliano 	if (err) {
33401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
33501a6c311SAlfredo Cardigliano 		return err;
33601a6c311SAlfredo Cardigliano 	}
33701a6c311SAlfredo Cardigliano 
33801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
33901a6c311SAlfredo Cardigliano 
340669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
341669c8de6SAlfredo Cardigliano 
342669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
343669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
344669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
345669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
346669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
347669c8de6SAlfredo Cardigliano 		return -ENOMEM;
348669c8de6SAlfredo Cardigliano 	}
349669c8de6SAlfredo Cardigliano 
350669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
351669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
352669c8de6SAlfredo Cardigliano 
353669c8de6SAlfredo Cardigliano 	return 0;
354669c8de6SAlfredo Cardigliano }
355669c8de6SAlfredo Cardigliano 
356669c8de6SAlfredo Cardigliano void
357669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
358669c8de6SAlfredo Cardigliano {
359*27b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
360*27b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
361*27b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
362*27b942c8SAlfredo Cardigliano 	}
363*27b942c8SAlfredo Cardigliano 
36401a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
36501a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
36601a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
36701a6c311SAlfredo Cardigliano 	}
36801a6c311SAlfredo Cardigliano 
369669c8de6SAlfredo Cardigliano 	if (lif->info) {
370669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
371669c8de6SAlfredo Cardigliano 		lif->info = NULL;
372669c8de6SAlfredo Cardigliano 	}
373669c8de6SAlfredo Cardigliano }
374669c8de6SAlfredo Cardigliano 
37501a6c311SAlfredo Cardigliano static void
37601a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
37701a6c311SAlfredo Cardigliano {
37801a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
37901a6c311SAlfredo Cardigliano 
38001a6c311SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED))
38101a6c311SAlfredo Cardigliano 		return;
38201a6c311SAlfredo Cardigliano 
38301a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
38401a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
38501a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
38601a6c311SAlfredo Cardigliano 
38701a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
38801a6c311SAlfredo Cardigliano }
38901a6c311SAlfredo Cardigliano 
39001a6c311SAlfredo Cardigliano bool
39101a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
39201a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
39301a6c311SAlfredo Cardigliano {
39401a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
39501a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
39601a6c311SAlfredo Cardigliano 
39701a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
39801a6c311SAlfredo Cardigliano 		return false;
39901a6c311SAlfredo Cardigliano 
40001a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
40101a6c311SAlfredo Cardigliano 
40201a6c311SAlfredo Cardigliano 	return true;
40301a6c311SAlfredo Cardigliano }
40401a6c311SAlfredo Cardigliano 
40501a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
40601a6c311SAlfredo Cardigliano int
40701a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
40801a6c311SAlfredo Cardigliano 		void *cb_arg)
40901a6c311SAlfredo Cardigliano {
41001a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
41101a6c311SAlfredo Cardigliano 	uint32_t work_done;
41201a6c311SAlfredo Cardigliano 
41301a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
41401a6c311SAlfredo Cardigliano 
41501a6c311SAlfredo Cardigliano 	return work_done;
41601a6c311SAlfredo Cardigliano }
41701a6c311SAlfredo Cardigliano 
418*27b942c8SAlfredo Cardigliano static void
419*27b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
420*27b942c8SAlfredo Cardigliano {
421*27b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
422*27b942c8SAlfredo Cardigliano 	bool link_up;
423*27b942c8SAlfredo Cardigliano 
424*27b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
425*27b942c8SAlfredo Cardigliano 
426*27b942c8SAlfredo Cardigliano 	if (!lif->info)
427*27b942c8SAlfredo Cardigliano 		return;
428*27b942c8SAlfredo Cardigliano 
429*27b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
430*27b942c8SAlfredo Cardigliano 
431*27b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
432*27b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
433*27b942c8SAlfredo Cardigliano 		return;
434*27b942c8SAlfredo Cardigliano 
435*27b942c8SAlfredo Cardigliano 	if (link_up) {
436*27b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
437*27b942c8SAlfredo Cardigliano 			lif->info->status.link_speed);
438*27b942c8SAlfredo Cardigliano 		adapter->link_speed = lif->info->status.link_speed;
439*27b942c8SAlfredo Cardigliano 	} else {
440*27b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
441*27b942c8SAlfredo Cardigliano 	}
442*27b942c8SAlfredo Cardigliano 
443*27b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
444*27b942c8SAlfredo Cardigliano }
445*27b942c8SAlfredo Cardigliano 
446*27b942c8SAlfredo Cardigliano static bool
447*27b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
448*27b942c8SAlfredo Cardigliano {
449*27b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
450*27b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
451*27b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
452*27b942c8SAlfredo Cardigliano 
453*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
454*27b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
455*27b942c8SAlfredo Cardigliano 
456*27b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
457*27b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
458*27b942c8SAlfredo Cardigliano 		return false;
459*27b942c8SAlfredo Cardigliano 
460*27b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
461*27b942c8SAlfredo Cardigliano 
462*27b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
463*27b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
464*27b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
465*27b942c8SAlfredo Cardigliano 			"Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
466*27b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
467*27b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
468*27b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
469*27b942c8SAlfredo Cardigliano 
470*27b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
471*27b942c8SAlfredo Cardigliano 
472*27b942c8SAlfredo Cardigliano 		break;
473*27b942c8SAlfredo Cardigliano 	default:
474*27b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
475*27b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
476*27b942c8SAlfredo Cardigliano 		break;
477*27b942c8SAlfredo Cardigliano 	}
478*27b942c8SAlfredo Cardigliano 
479*27b942c8SAlfredo Cardigliano 	return true;
480*27b942c8SAlfredo Cardigliano }
481*27b942c8SAlfredo Cardigliano 
482*27b942c8SAlfredo Cardigliano int
483*27b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
484*27b942c8SAlfredo Cardigliano {
485*27b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
486*27b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
487*27b942c8SAlfredo Cardigliano 	uint32_t work_done;
488*27b942c8SAlfredo Cardigliano 
489*27b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
490*27b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
491*27b942c8SAlfredo Cardigliano 		return -1;
492*27b942c8SAlfredo Cardigliano 	}
493*27b942c8SAlfredo Cardigliano 
494*27b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
495*27b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
496*27b942c8SAlfredo Cardigliano 
497*27b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
498*27b942c8SAlfredo Cardigliano 
499*27b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
500*27b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
501*27b942c8SAlfredo Cardigliano 
502*27b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
503*27b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
504*27b942c8SAlfredo Cardigliano 
505*27b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
506*27b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
507*27b942c8SAlfredo Cardigliano 
508*27b942c8SAlfredo Cardigliano 	return 0;
509*27b942c8SAlfredo Cardigliano }
510*27b942c8SAlfredo Cardigliano 
51101a6c311SAlfredo Cardigliano static int
51201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
51301a6c311SAlfredo Cardigliano {
51401a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
51501a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
51601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
51701a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
51801a6c311SAlfredo Cardigliano 	int err;
51901a6c311SAlfredo Cardigliano 
52001a6c311SAlfredo Cardigliano 	ionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index);
52101a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
52201a6c311SAlfredo Cardigliano 	if (err)
52301a6c311SAlfredo Cardigliano 		return err;
52401a6c311SAlfredo Cardigliano 
52501a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
52601a6c311SAlfredo Cardigliano 
52701a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
52801a6c311SAlfredo Cardigliano 	q->hw_index = comp.hw_index;
52901a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
53001a6c311SAlfredo Cardigliano 
53101a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
53201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
53301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
53401a6c311SAlfredo Cardigliano 
53501a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
53601a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
53701a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
53801a6c311SAlfredo Cardigliano 
53901a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
54001a6c311SAlfredo Cardigliano 
54101a6c311SAlfredo Cardigliano 	return 0;
54201a6c311SAlfredo Cardigliano }
54301a6c311SAlfredo Cardigliano 
544*27b942c8SAlfredo Cardigliano static int
545*27b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
546*27b942c8SAlfredo Cardigliano {
547*27b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
548*27b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
549*27b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
550*27b942c8SAlfredo Cardigliano 	int err;
551*27b942c8SAlfredo Cardigliano 
552*27b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
553*27b942c8SAlfredo Cardigliano 		.pending_work = true,
554*27b942c8SAlfredo Cardigliano 		.cmd.q_init = {
555*27b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
556*27b942c8SAlfredo Cardigliano 			.lif_index = lif->index,
557*27b942c8SAlfredo Cardigliano 			.type = q->type,
558*27b942c8SAlfredo Cardigliano 			.index = q->index,
559*27b942c8SAlfredo Cardigliano 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
560*27b942c8SAlfredo Cardigliano 			.intr_index = qcq->intr.index,
561*27b942c8SAlfredo Cardigliano 			.pid = q->pid,
562*27b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
563*27b942c8SAlfredo Cardigliano 			.ring_base = q->base_pa,
564*27b942c8SAlfredo Cardigliano 		}
565*27b942c8SAlfredo Cardigliano 	};
566*27b942c8SAlfredo Cardigliano 
567*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.pid %d", ctx.cmd.q_init.pid);
568*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
569*27b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.index);
570*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
571*27b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
572*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
573*27b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
574*27b942c8SAlfredo Cardigliano 
575*27b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
576*27b942c8SAlfredo Cardigliano 	if (err)
577*27b942c8SAlfredo Cardigliano 		return err;
578*27b942c8SAlfredo Cardigliano 
579*27b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
580*27b942c8SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
581*27b942c8SAlfredo Cardigliano 	q->db = NULL;
582*27b942c8SAlfredo Cardigliano 
583*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
584*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
585*27b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
586*27b942c8SAlfredo Cardigliano 
587*27b942c8SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
588*27b942c8SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
589*27b942c8SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
590*27b942c8SAlfredo Cardigliano 
591*27b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
592*27b942c8SAlfredo Cardigliano 
593*27b942c8SAlfredo Cardigliano 	return 0;
594*27b942c8SAlfredo Cardigliano }
595*27b942c8SAlfredo Cardigliano 
596669c8de6SAlfredo Cardigliano int
597669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
598669c8de6SAlfredo Cardigliano {
599669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
600669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
601669c8de6SAlfredo Cardigliano 	int err;
602669c8de6SAlfredo Cardigliano 
603669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
604669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
605669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
606669c8de6SAlfredo Cardigliano 	if (err)
607669c8de6SAlfredo Cardigliano 		return err;
608669c8de6SAlfredo Cardigliano 
609669c8de6SAlfredo Cardigliano 	lif->hw_index = comp.hw_index;
610669c8de6SAlfredo Cardigliano 
61101a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
61201a6c311SAlfredo Cardigliano 	if (err)
61301a6c311SAlfredo Cardigliano 		return err;
61401a6c311SAlfredo Cardigliano 
615*27b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
616*27b942c8SAlfredo Cardigliano 	if (err)
617*27b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
618*27b942c8SAlfredo Cardigliano 
619669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
620669c8de6SAlfredo Cardigliano 
621669c8de6SAlfredo Cardigliano 	return 0;
622*27b942c8SAlfredo Cardigliano 
623*27b942c8SAlfredo Cardigliano err_out_adminq_deinit:
624*27b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
625*27b942c8SAlfredo Cardigliano 
626*27b942c8SAlfredo Cardigliano 	return err;
627669c8de6SAlfredo Cardigliano }
628669c8de6SAlfredo Cardigliano 
629669c8de6SAlfredo Cardigliano void
630669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
631669c8de6SAlfredo Cardigliano {
632669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
633669c8de6SAlfredo Cardigliano 		return;
634669c8de6SAlfredo Cardigliano 
635*27b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
63601a6c311SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
63701a6c311SAlfredo Cardigliano 
638669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
639669c8de6SAlfredo Cardigliano }
640669c8de6SAlfredo Cardigliano 
641669c8de6SAlfredo Cardigliano int
642669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
643669c8de6SAlfredo Cardigliano {
644669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
645669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
646669c8de6SAlfredo Cardigliano 	int err;
647669c8de6SAlfredo Cardigliano 	unsigned int i;
648669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
649669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
650669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
651669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
652669c8de6SAlfredo Cardigliano 	unsigned int nwords;
653669c8de6SAlfredo Cardigliano 
654669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
655669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
656669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
657669c8de6SAlfredo Cardigliano 	if (err)
658669c8de6SAlfredo Cardigliano 		return (err);
659669c8de6SAlfredo Cardigliano 
660669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
661669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
662669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
663669c8de6SAlfredo Cardigliano 
664669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
665669c8de6SAlfredo Cardigliano 		ident->lif.capabilities);
666669c8de6SAlfredo Cardigliano 
667669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
668669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_ucast_filters);
669669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
670669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_mcast_filters);
671669c8de6SAlfredo Cardigliano 
672669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
673669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.features);
674669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
675669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
676669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
677669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
678669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
679669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
680669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
681669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
682669c8de6SAlfredo Cardigliano 
683669c8de6SAlfredo Cardigliano 	return 0;
684669c8de6SAlfredo Cardigliano }
685669c8de6SAlfredo Cardigliano 
686669c8de6SAlfredo Cardigliano int
687669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
688669c8de6SAlfredo Cardigliano {
689669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
690669c8de6SAlfredo Cardigliano 	uint32_t nlifs = ident->dev.nlifs;
691669c8de6SAlfredo Cardigliano 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
692669c8de6SAlfredo Cardigliano 
693669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
694669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
695669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
696669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
697669c8de6SAlfredo Cardigliano 
698669c8de6SAlfredo Cardigliano 	nintrs = nlifs * 1 /* notifyq */;
699669c8de6SAlfredo Cardigliano 
700669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
701669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "At most %d intr queues supported, minimum required is %u",
702669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
703669c8de6SAlfredo Cardigliano 		return -ENOSPC;
704669c8de6SAlfredo Cardigliano 	}
705669c8de6SAlfredo Cardigliano 
706669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
707669c8de6SAlfredo Cardigliano 
708669c8de6SAlfredo Cardigliano 	return 0;
709669c8de6SAlfredo Cardigliano }
710