18c2ecf20Sopenharmony_ci/******************************************************************************
28c2ecf20Sopenharmony_ci * This software may be used and distributed according to the terms of
38c2ecf20Sopenharmony_ci * the GNU General Public License (GPL), incorporated herein by reference.
48c2ecf20Sopenharmony_ci * Drivers based on or derived from this code fall under the GPL and must
58c2ecf20Sopenharmony_ci * retain the authorship, copyright and license notice.  This file is not
68c2ecf20Sopenharmony_ci * a complete program and may only be used when the entire operating
78c2ecf20Sopenharmony_ci * system is licensed under the GPL.
88c2ecf20Sopenharmony_ci * See the file COPYING in this distribution for more information.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * vxge-traffic.c: Driver for Exar Corp's X3100 Series 10GbE PCIe I/O
118c2ecf20Sopenharmony_ci *                 Virtualized Server Adapter.
128c2ecf20Sopenharmony_ci * Copyright(c) 2002-2010 Exar Corp.
138c2ecf20Sopenharmony_ci ******************************************************************************/
148c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
158c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h>
168c2ecf20Sopenharmony_ci#include <linux/prefetch.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "vxge-traffic.h"
198c2ecf20Sopenharmony_ci#include "vxge-config.h"
208c2ecf20Sopenharmony_ci#include "vxge-main.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/*
238c2ecf20Sopenharmony_ci * vxge_hw_vpath_intr_enable - Enable vpath interrupts.
248c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * Enable vpath interrupts. The function is to be executed the last in
278c2ecf20Sopenharmony_ci * vpath initialization sequence.
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_intr_disable()
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_intr_enable(struct __vxge_hw_vpath_handle *vp)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
348c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
358c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
368c2ecf20Sopenharmony_ci	if (vp == NULL) {
378c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
388c2ecf20Sopenharmony_ci		goto exit;
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	vpath = vp->vpath;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
448c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
458c2ecf20Sopenharmony_ci		goto exit;
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_reg);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
538c2ecf20Sopenharmony_ci			&vp_reg->general_errors_reg);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
568c2ecf20Sopenharmony_ci			&vp_reg->pci_config_errors_reg);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
598c2ecf20Sopenharmony_ci			&vp_reg->mrpcim_to_vpath_alarm_reg);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
628c2ecf20Sopenharmony_ci			&vp_reg->srpcim_to_vpath_alarm_reg);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
658c2ecf20Sopenharmony_ci			&vp_reg->vpath_ppif_int_status);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
688c2ecf20Sopenharmony_ci			&vp_reg->srpcim_msg_to_vpath_reg);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
718c2ecf20Sopenharmony_ci			&vp_reg->vpath_pcipif_int_status);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
748c2ecf20Sopenharmony_ci			&vp_reg->prc_alarm_reg);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
778c2ecf20Sopenharmony_ci			&vp_reg->wrdma_alarm_status);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
808c2ecf20Sopenharmony_ci			&vp_reg->asic_ntwk_vp_err_reg);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
838c2ecf20Sopenharmony_ci			&vp_reg->xgmac_vp_int_status);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	readq(&vp_reg->vpath_general_int_status);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* Mask unwanted interrupts */
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
908c2ecf20Sopenharmony_ci			&vp_reg->vpath_pcipif_int_mask);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
938c2ecf20Sopenharmony_ci			&vp_reg->srpcim_msg_to_vpath_mask);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
968c2ecf20Sopenharmony_ci			&vp_reg->srpcim_to_vpath_alarm_mask);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
998c2ecf20Sopenharmony_ci			&vp_reg->mrpcim_to_vpath_alarm_mask);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1028c2ecf20Sopenharmony_ci			&vp_reg->pci_config_errors_mask);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	/* Unmask the individual interrupts */
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	writeq((u32)vxge_bVALn((VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO1_OVRFLOW|
1078c2ecf20Sopenharmony_ci		VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO2_OVRFLOW|
1088c2ecf20Sopenharmony_ci		VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ|
1098c2ecf20Sopenharmony_ci		VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR), 0, 32),
1108c2ecf20Sopenharmony_ci		&vp_reg->general_errors_mask);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
1138c2ecf20Sopenharmony_ci		(u32)vxge_bVALn((VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_OVRWR|
1148c2ecf20Sopenharmony_ci		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_OVRWR|
1158c2ecf20Sopenharmony_ci		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_POISON|
1168c2ecf20Sopenharmony_ci		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_POISON|
1178c2ecf20Sopenharmony_ci		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_DMA_ERR|
1188c2ecf20Sopenharmony_ci		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_DMA_ERR), 0, 32),
1198c2ecf20Sopenharmony_ci		&vp_reg->kdfcctl_errors_mask);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(0, &vp_reg->vpath_ppif_int_mask);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
1248c2ecf20Sopenharmony_ci		(u32)vxge_bVALn(VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP, 0, 32),
1258c2ecf20Sopenharmony_ci		&vp_reg->prc_alarm_mask);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(0, &vp_reg->wrdma_alarm_mask);
1288c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(0, &vp_reg->xgmac_vp_int_mask);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	if (vpath->hldev->first_vp_id != vpath->vp_id)
1318c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1328c2ecf20Sopenharmony_ci			&vp_reg->asic_ntwk_vp_err_mask);
1338c2ecf20Sopenharmony_ci	else
1348c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn((
1358c2ecf20Sopenharmony_ci		VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_FAULT |
1368c2ecf20Sopenharmony_ci		VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_OK), 0, 32),
1378c2ecf20Sopenharmony_ci		&vp_reg->asic_ntwk_vp_err_mask);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(0,
1408c2ecf20Sopenharmony_ci		&vp_reg->vpath_general_int_mask);
1418c2ecf20Sopenharmony_ciexit:
1428c2ecf20Sopenharmony_ci	return status;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/*
1478c2ecf20Sopenharmony_ci * vxge_hw_vpath_intr_disable - Disable vpath interrupts.
1488c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
1498c2ecf20Sopenharmony_ci *
1508c2ecf20Sopenharmony_ci * Disable vpath interrupts. The function is to be executed the last in
1518c2ecf20Sopenharmony_ci * vpath initialization sequence.
1528c2ecf20Sopenharmony_ci *
1538c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_intr_enable()
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_intr_disable(
1568c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
1598c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
1608c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
1618c2ecf20Sopenharmony_ci	if (vp == NULL) {
1628c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
1638c2ecf20Sopenharmony_ci		goto exit;
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	vpath = vp->vpath;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
1698c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
1708c2ecf20Sopenharmony_ci		goto exit;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
1758c2ecf20Sopenharmony_ci		(u32)VXGE_HW_INTR_MASK_ALL,
1768c2ecf20Sopenharmony_ci		&vp_reg->vpath_general_int_mask);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_mask);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1818c2ecf20Sopenharmony_ci			&vp_reg->general_errors_mask);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1848c2ecf20Sopenharmony_ci			&vp_reg->pci_config_errors_mask);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1878c2ecf20Sopenharmony_ci			&vp_reg->mrpcim_to_vpath_alarm_mask);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1908c2ecf20Sopenharmony_ci			&vp_reg->srpcim_to_vpath_alarm_mask);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1938c2ecf20Sopenharmony_ci			&vp_reg->vpath_ppif_int_mask);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1968c2ecf20Sopenharmony_ci			&vp_reg->srpcim_msg_to_vpath_mask);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
1998c2ecf20Sopenharmony_ci			&vp_reg->vpath_pcipif_int_mask);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
2028c2ecf20Sopenharmony_ci			&vp_reg->wrdma_alarm_mask);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
2058c2ecf20Sopenharmony_ci			&vp_reg->prc_alarm_mask);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
2088c2ecf20Sopenharmony_ci			&vp_reg->xgmac_vp_int_mask);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
2118c2ecf20Sopenharmony_ci			&vp_reg->asic_ntwk_vp_err_mask);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ciexit:
2148c2ecf20Sopenharmony_ci	return status;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_civoid vxge_hw_vpath_tti_ci_set(struct __vxge_hw_fifo *fifo)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
2208c2ecf20Sopenharmony_ci	struct vxge_hw_vp_config *config;
2218c2ecf20Sopenharmony_ci	u64 val64;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	if (fifo->config->enable != VXGE_HW_FIFO_ENABLE)
2248c2ecf20Sopenharmony_ci		return;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	vp_reg = fifo->vp_reg;
2278c2ecf20Sopenharmony_ci	config = container_of(fifo->config, struct vxge_hw_vp_config, fifo);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
2308c2ecf20Sopenharmony_ci		config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
2318c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
2328c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
2338c2ecf20Sopenharmony_ci		fifo->tim_tti_cfg1_saved = val64;
2348c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
2358c2ecf20Sopenharmony_ci	}
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_civoid vxge_hw_vpath_dynamic_rti_ci_set(struct __vxge_hw_ring *ring)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	u64 val64 = ring->tim_rti_cfg1_saved;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
2438c2ecf20Sopenharmony_ci	ring->tim_rti_cfg1_saved = val64;
2448c2ecf20Sopenharmony_ci	writeq(val64, &ring->vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_civoid vxge_hw_vpath_dynamic_tti_rtimer_set(struct __vxge_hw_fifo *fifo)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	u64 val64 = fifo->tim_tti_cfg3_saved;
2508c2ecf20Sopenharmony_ci	u64 timer = (fifo->rtimer * 1000) / 272;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(0x3ffffff);
2538c2ecf20Sopenharmony_ci	if (timer)
2548c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(timer) |
2558c2ecf20Sopenharmony_ci			VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(5);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	writeq(val64, &fifo->vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
2588c2ecf20Sopenharmony_ci	/* tti_cfg3_saved is not updated again because it is
2598c2ecf20Sopenharmony_ci	 * initialized at one place only - init time.
2608c2ecf20Sopenharmony_ci	 */
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_civoid vxge_hw_vpath_dynamic_rti_rtimer_set(struct __vxge_hw_ring *ring)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	u64 val64 = ring->tim_rti_cfg3_saved;
2668c2ecf20Sopenharmony_ci	u64 timer = (ring->rtimer * 1000) / 272;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(0x3ffffff);
2698c2ecf20Sopenharmony_ci	if (timer)
2708c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(timer) |
2718c2ecf20Sopenharmony_ci			VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(4);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	writeq(val64, &ring->vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
2748c2ecf20Sopenharmony_ci	/* rti_cfg3_saved is not updated again because it is
2758c2ecf20Sopenharmony_ci	 * initialized at one place only - init time.
2768c2ecf20Sopenharmony_ci	 */
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci/**
2808c2ecf20Sopenharmony_ci * vxge_hw_channel_msix_mask - Mask MSIX Vector.
2818c2ecf20Sopenharmony_ci * @channel: Channel for rx or tx handle
2828c2ecf20Sopenharmony_ci * @msix_id:  MSIX ID
2838c2ecf20Sopenharmony_ci *
2848c2ecf20Sopenharmony_ci * The function masks the msix interrupt for the given msix_id
2858c2ecf20Sopenharmony_ci *
2868c2ecf20Sopenharmony_ci * Returns: 0
2878c2ecf20Sopenharmony_ci */
2888c2ecf20Sopenharmony_civoid vxge_hw_channel_msix_mask(struct __vxge_hw_channel *channel, int msix_id)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
2928c2ecf20Sopenharmony_ci		(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
2938c2ecf20Sopenharmony_ci		&channel->common_reg->set_msix_mask_vect[msix_id%4]);
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci/**
2978c2ecf20Sopenharmony_ci * vxge_hw_channel_msix_unmask - Unmask the MSIX Vector.
2988c2ecf20Sopenharmony_ci * @channel: Channel for rx or tx handle
2998c2ecf20Sopenharmony_ci * @msix_id:  MSI ID
3008c2ecf20Sopenharmony_ci *
3018c2ecf20Sopenharmony_ci * The function unmasks the msix interrupt for the given msix_id
3028c2ecf20Sopenharmony_ci *
3038c2ecf20Sopenharmony_ci * Returns: 0
3048c2ecf20Sopenharmony_ci */
3058c2ecf20Sopenharmony_civoid
3068c2ecf20Sopenharmony_civxge_hw_channel_msix_unmask(struct __vxge_hw_channel *channel, int msix_id)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
3108c2ecf20Sopenharmony_ci		(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
3118c2ecf20Sopenharmony_ci		&channel->common_reg->clear_msix_mask_vect[msix_id%4]);
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci/**
3158c2ecf20Sopenharmony_ci * vxge_hw_channel_msix_clear - Unmask the MSIX Vector.
3168c2ecf20Sopenharmony_ci * @channel: Channel for rx or tx handle
3178c2ecf20Sopenharmony_ci * @msix_id:  MSI ID
3188c2ecf20Sopenharmony_ci *
3198c2ecf20Sopenharmony_ci * The function unmasks the msix interrupt for the given msix_id
3208c2ecf20Sopenharmony_ci * if configured in MSIX oneshot mode
3218c2ecf20Sopenharmony_ci *
3228c2ecf20Sopenharmony_ci * Returns: 0
3238c2ecf20Sopenharmony_ci */
3248c2ecf20Sopenharmony_civoid vxge_hw_channel_msix_clear(struct __vxge_hw_channel *channel, int msix_id)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
3278c2ecf20Sopenharmony_ci		(u32) vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
3288c2ecf20Sopenharmony_ci		&channel->common_reg->clr_msix_one_shot_vec[msix_id % 4]);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci/**
3328c2ecf20Sopenharmony_ci * vxge_hw_device_set_intr_type - Updates the configuration
3338c2ecf20Sopenharmony_ci *		with new interrupt type.
3348c2ecf20Sopenharmony_ci * @hldev: HW device handle.
3358c2ecf20Sopenharmony_ci * @intr_mode: New interrupt type
3368c2ecf20Sopenharmony_ci */
3378c2ecf20Sopenharmony_ciu32 vxge_hw_device_set_intr_type(struct __vxge_hw_device *hldev, u32 intr_mode)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if ((intr_mode != VXGE_HW_INTR_MODE_IRQLINE) &&
3418c2ecf20Sopenharmony_ci	   (intr_mode != VXGE_HW_INTR_MODE_MSIX) &&
3428c2ecf20Sopenharmony_ci	   (intr_mode != VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) &&
3438c2ecf20Sopenharmony_ci	   (intr_mode != VXGE_HW_INTR_MODE_DEF))
3448c2ecf20Sopenharmony_ci		intr_mode = VXGE_HW_INTR_MODE_IRQLINE;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	hldev->config.intr_mode = intr_mode;
3478c2ecf20Sopenharmony_ci	return intr_mode;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci/**
3518c2ecf20Sopenharmony_ci * vxge_hw_device_intr_enable - Enable interrupts.
3528c2ecf20Sopenharmony_ci * @hldev: HW device handle.
3538c2ecf20Sopenharmony_ci *
3548c2ecf20Sopenharmony_ci * Enable Titan interrupts. The function is to be executed the last in
3558c2ecf20Sopenharmony_ci * Titan initialization sequence.
3568c2ecf20Sopenharmony_ci *
3578c2ecf20Sopenharmony_ci * See also: vxge_hw_device_intr_disable()
3588c2ecf20Sopenharmony_ci */
3598c2ecf20Sopenharmony_civoid vxge_hw_device_intr_enable(struct __vxge_hw_device *hldev)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	u32 i;
3628c2ecf20Sopenharmony_ci	u64 val64;
3638c2ecf20Sopenharmony_ci	u32 val32;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	vxge_hw_device_mask_all(hldev);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
3708c2ecf20Sopenharmony_ci			continue;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci		vxge_hw_vpath_intr_enable(
3738c2ecf20Sopenharmony_ci			VXGE_HW_VIRTUAL_PATH_HANDLE(&hldev->virtual_paths[i]));
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	if (hldev->config.intr_mode == VXGE_HW_INTR_MODE_IRQLINE) {
3778c2ecf20Sopenharmony_ci		val64 = hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
3788c2ecf20Sopenharmony_ci			hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX];
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci		if (val64 != 0) {
3818c2ecf20Sopenharmony_ci			writeq(val64, &hldev->common_reg->tim_int_status0);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci			writeq(~val64, &hldev->common_reg->tim_int_mask0);
3848c2ecf20Sopenharmony_ci		}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		val32 = hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
3878c2ecf20Sopenharmony_ci			hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX];
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		if (val32 != 0) {
3908c2ecf20Sopenharmony_ci			__vxge_hw_pio_mem_write32_upper(val32,
3918c2ecf20Sopenharmony_ci					&hldev->common_reg->tim_int_status1);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci			__vxge_hw_pio_mem_write32_upper(~val32,
3948c2ecf20Sopenharmony_ci					&hldev->common_reg->tim_int_mask1);
3958c2ecf20Sopenharmony_ci		}
3968c2ecf20Sopenharmony_ci	}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	val64 = readq(&hldev->common_reg->titan_general_int_status);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	vxge_hw_device_unmask_all(hldev);
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci/**
4048c2ecf20Sopenharmony_ci * vxge_hw_device_intr_disable - Disable Titan interrupts.
4058c2ecf20Sopenharmony_ci * @hldev: HW device handle.
4068c2ecf20Sopenharmony_ci *
4078c2ecf20Sopenharmony_ci * Disable Titan interrupts.
4088c2ecf20Sopenharmony_ci *
4098c2ecf20Sopenharmony_ci * See also: vxge_hw_device_intr_enable()
4108c2ecf20Sopenharmony_ci */
4118c2ecf20Sopenharmony_civoid vxge_hw_device_intr_disable(struct __vxge_hw_device *hldev)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	u32 i;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	vxge_hw_device_mask_all(hldev);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	/* mask all the tim interrupts */
4188c2ecf20Sopenharmony_ci	writeq(VXGE_HW_INTR_MASK_ALL, &hldev->common_reg->tim_int_mask0);
4198c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(VXGE_HW_DEFAULT_32,
4208c2ecf20Sopenharmony_ci		&hldev->common_reg->tim_int_mask1);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
4258c2ecf20Sopenharmony_ci			continue;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci		vxge_hw_vpath_intr_disable(
4288c2ecf20Sopenharmony_ci			VXGE_HW_VIRTUAL_PATH_HANDLE(&hldev->virtual_paths[i]));
4298c2ecf20Sopenharmony_ci	}
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/**
4338c2ecf20Sopenharmony_ci * vxge_hw_device_mask_all - Mask all device interrupts.
4348c2ecf20Sopenharmony_ci * @hldev: HW device handle.
4358c2ecf20Sopenharmony_ci *
4368c2ecf20Sopenharmony_ci * Mask	all device interrupts.
4378c2ecf20Sopenharmony_ci *
4388c2ecf20Sopenharmony_ci * See also: vxge_hw_device_unmask_all()
4398c2ecf20Sopenharmony_ci */
4408c2ecf20Sopenharmony_civoid vxge_hw_device_mask_all(struct __vxge_hw_device *hldev)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	u64 val64;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	val64 = VXGE_HW_TITAN_MASK_ALL_INT_ALARM |
4458c2ecf20Sopenharmony_ci		VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
4488c2ecf20Sopenharmony_ci				&hldev->common_reg->titan_mask_all_int);
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci/**
4528c2ecf20Sopenharmony_ci * vxge_hw_device_unmask_all - Unmask all device interrupts.
4538c2ecf20Sopenharmony_ci * @hldev: HW device handle.
4548c2ecf20Sopenharmony_ci *
4558c2ecf20Sopenharmony_ci * Unmask all device interrupts.
4568c2ecf20Sopenharmony_ci *
4578c2ecf20Sopenharmony_ci * See also: vxge_hw_device_mask_all()
4588c2ecf20Sopenharmony_ci */
4598c2ecf20Sopenharmony_civoid vxge_hw_device_unmask_all(struct __vxge_hw_device *hldev)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	u64 val64 = 0;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	if (hldev->config.intr_mode == VXGE_HW_INTR_MODE_IRQLINE)
4648c2ecf20Sopenharmony_ci		val64 =  VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
4678c2ecf20Sopenharmony_ci			&hldev->common_reg->titan_mask_all_int);
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci/**
4718c2ecf20Sopenharmony_ci * vxge_hw_device_flush_io - Flush io writes.
4728c2ecf20Sopenharmony_ci * @hldev: HW device handle.
4738c2ecf20Sopenharmony_ci *
4748c2ecf20Sopenharmony_ci * The function	performs a read operation to flush io writes.
4758c2ecf20Sopenharmony_ci *
4768c2ecf20Sopenharmony_ci * Returns: void
4778c2ecf20Sopenharmony_ci */
4788c2ecf20Sopenharmony_civoid vxge_hw_device_flush_io(struct __vxge_hw_device *hldev)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	readl(&hldev->common_reg->titan_general_int_status);
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci/**
4848c2ecf20Sopenharmony_ci * __vxge_hw_device_handle_error - Handle error
4858c2ecf20Sopenharmony_ci * @hldev: HW device
4868c2ecf20Sopenharmony_ci * @vp_id: Vpath Id
4878c2ecf20Sopenharmony_ci * @type: Error type. Please see enum vxge_hw_event{}
4888c2ecf20Sopenharmony_ci *
4898c2ecf20Sopenharmony_ci * Handle error.
4908c2ecf20Sopenharmony_ci */
4918c2ecf20Sopenharmony_cistatic enum vxge_hw_status
4928c2ecf20Sopenharmony_ci__vxge_hw_device_handle_error(struct __vxge_hw_device *hldev, u32 vp_id,
4938c2ecf20Sopenharmony_ci			      enum vxge_hw_event type)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	switch (type) {
4968c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_UNKNOWN:
4978c2ecf20Sopenharmony_ci		break;
4988c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_RESET_START:
4998c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_RESET_COMPLETE:
5008c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_LINK_DOWN:
5018c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_LINK_UP:
5028c2ecf20Sopenharmony_ci		goto out;
5038c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_ALARM_CLEARED:
5048c2ecf20Sopenharmony_ci		goto out;
5058c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_ECCERR:
5068c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_MRPCIM_ECCERR:
5078c2ecf20Sopenharmony_ci		goto out;
5088c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_FIFO_ERR:
5098c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_VPATH_ERR:
5108c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_CRITICAL_ERR:
5118c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_SERR:
5128c2ecf20Sopenharmony_ci		break;
5138c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_SRPCIM_SERR:
5148c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_MRPCIM_SERR:
5158c2ecf20Sopenharmony_ci		goto out;
5168c2ecf20Sopenharmony_ci	case VXGE_HW_EVENT_SLOT_FREEZE:
5178c2ecf20Sopenharmony_ci		break;
5188c2ecf20Sopenharmony_ci	default:
5198c2ecf20Sopenharmony_ci		vxge_assert(0);
5208c2ecf20Sopenharmony_ci		goto out;
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	/* notify driver */
5248c2ecf20Sopenharmony_ci	if (hldev->uld_callbacks->crit_err)
5258c2ecf20Sopenharmony_ci		hldev->uld_callbacks->crit_err(hldev,
5268c2ecf20Sopenharmony_ci			type, vp_id);
5278c2ecf20Sopenharmony_ciout:
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci/*
5338c2ecf20Sopenharmony_ci * __vxge_hw_device_handle_link_down_ind
5348c2ecf20Sopenharmony_ci * @hldev: HW device handle.
5358c2ecf20Sopenharmony_ci *
5368c2ecf20Sopenharmony_ci * Link down indication handler. The function is invoked by HW when
5378c2ecf20Sopenharmony_ci * Titan indicates that the link is down.
5388c2ecf20Sopenharmony_ci */
5398c2ecf20Sopenharmony_cistatic enum vxge_hw_status
5408c2ecf20Sopenharmony_ci__vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev)
5418c2ecf20Sopenharmony_ci{
5428c2ecf20Sopenharmony_ci	/*
5438c2ecf20Sopenharmony_ci	 * If the previous link state is not down, return.
5448c2ecf20Sopenharmony_ci	 */
5458c2ecf20Sopenharmony_ci	if (hldev->link_state == VXGE_HW_LINK_DOWN)
5468c2ecf20Sopenharmony_ci		goto exit;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	hldev->link_state = VXGE_HW_LINK_DOWN;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	/* notify driver */
5518c2ecf20Sopenharmony_ci	if (hldev->uld_callbacks->link_down)
5528c2ecf20Sopenharmony_ci		hldev->uld_callbacks->link_down(hldev);
5538c2ecf20Sopenharmony_ciexit:
5548c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci/*
5588c2ecf20Sopenharmony_ci * __vxge_hw_device_handle_link_up_ind
5598c2ecf20Sopenharmony_ci * @hldev: HW device handle.
5608c2ecf20Sopenharmony_ci *
5618c2ecf20Sopenharmony_ci * Link up indication handler. The function is invoked by HW when
5628c2ecf20Sopenharmony_ci * Titan indicates that the link is up for programmable amount of time.
5638c2ecf20Sopenharmony_ci */
5648c2ecf20Sopenharmony_cistatic enum vxge_hw_status
5658c2ecf20Sopenharmony_ci__vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	/*
5688c2ecf20Sopenharmony_ci	 * If the previous link state is not down, return.
5698c2ecf20Sopenharmony_ci	 */
5708c2ecf20Sopenharmony_ci	if (hldev->link_state == VXGE_HW_LINK_UP)
5718c2ecf20Sopenharmony_ci		goto exit;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	hldev->link_state = VXGE_HW_LINK_UP;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/* notify driver */
5768c2ecf20Sopenharmony_ci	if (hldev->uld_callbacks->link_up)
5778c2ecf20Sopenharmony_ci		hldev->uld_callbacks->link_up(hldev);
5788c2ecf20Sopenharmony_ciexit:
5798c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci/*
5838c2ecf20Sopenharmony_ci * __vxge_hw_vpath_alarm_process - Process Alarms.
5848c2ecf20Sopenharmony_ci * @vpath: Virtual Path.
5858c2ecf20Sopenharmony_ci * @skip_alarms: Do not clear the alarms
5868c2ecf20Sopenharmony_ci *
5878c2ecf20Sopenharmony_ci * Process vpath alarms.
5888c2ecf20Sopenharmony_ci *
5898c2ecf20Sopenharmony_ci */
5908c2ecf20Sopenharmony_cistatic enum vxge_hw_status
5918c2ecf20Sopenharmony_ci__vxge_hw_vpath_alarm_process(struct __vxge_hw_virtualpath *vpath,
5928c2ecf20Sopenharmony_ci			      u32 skip_alarms)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	u64 val64;
5958c2ecf20Sopenharmony_ci	u64 alarm_status;
5968c2ecf20Sopenharmony_ci	u64 pic_status;
5978c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = NULL;
5988c2ecf20Sopenharmony_ci	enum vxge_hw_event alarm_event = VXGE_HW_EVENT_UNKNOWN;
5998c2ecf20Sopenharmony_ci	u64 mask64;
6008c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_stats_sw_info *sw_stats;
6018c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	if (vpath == NULL) {
6048c2ecf20Sopenharmony_ci		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
6058c2ecf20Sopenharmony_ci			alarm_event);
6068c2ecf20Sopenharmony_ci		goto out2;
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	hldev = vpath->hldev;
6108c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
6118c2ecf20Sopenharmony_ci	alarm_status = readq(&vp_reg->vpath_general_int_status);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	if (alarm_status == VXGE_HW_ALL_FOXES) {
6148c2ecf20Sopenharmony_ci		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_SLOT_FREEZE,
6158c2ecf20Sopenharmony_ci			alarm_event);
6168c2ecf20Sopenharmony_ci		goto out;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	sw_stats = vpath->sw_stats;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (alarm_status & ~(
6228c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT |
6238c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT |
6248c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT |
6258c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) {
6268c2ecf20Sopenharmony_ci		sw_stats->error_stats.unknown_alarms++;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
6298c2ecf20Sopenharmony_ci			alarm_event);
6308c2ecf20Sopenharmony_ci		goto out;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT) {
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->xgmac_vp_int_status);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci		if (val64 &
6388c2ecf20Sopenharmony_ci		VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT) {
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci			val64 = readq(&vp_reg->asic_ntwk_vp_err_reg);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci			if (((val64 &
6438c2ecf20Sopenharmony_ci			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT) &&
6448c2ecf20Sopenharmony_ci			     (!(val64 &
6458c2ecf20Sopenharmony_ci				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK))) ||
6468c2ecf20Sopenharmony_ci			    ((val64 &
6478c2ecf20Sopenharmony_ci			     VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR) &&
6488c2ecf20Sopenharmony_ci			     (!(val64 &
6498c2ecf20Sopenharmony_ci				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR)
6508c2ecf20Sopenharmony_ci				     ))) {
6518c2ecf20Sopenharmony_ci				sw_stats->error_stats.network_sustained_fault++;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci				writeq(
6548c2ecf20Sopenharmony_ci				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT,
6558c2ecf20Sopenharmony_ci					&vp_reg->asic_ntwk_vp_err_mask);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci				__vxge_hw_device_handle_link_down_ind(hldev);
6588c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
6598c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_LINK_DOWN, alarm_event);
6608c2ecf20Sopenharmony_ci			}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci			if (((val64 &
6638c2ecf20Sopenharmony_ci			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK) &&
6648c2ecf20Sopenharmony_ci			     (!(val64 &
6658c2ecf20Sopenharmony_ci				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT))) ||
6668c2ecf20Sopenharmony_ci			    ((val64 &
6678c2ecf20Sopenharmony_ci			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR) &&
6688c2ecf20Sopenharmony_ci			     (!(val64 &
6698c2ecf20Sopenharmony_ci				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR)
6708c2ecf20Sopenharmony_ci				     ))) {
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci				sw_stats->error_stats.network_sustained_ok++;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci				writeq(
6758c2ecf20Sopenharmony_ci				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK,
6768c2ecf20Sopenharmony_ci					&vp_reg->asic_ntwk_vp_err_mask);
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci				__vxge_hw_device_handle_link_up_ind(hldev);
6798c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
6808c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_LINK_UP, alarm_event);
6818c2ecf20Sopenharmony_ci			}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci			writeq(VXGE_HW_INTR_MASK_ALL,
6848c2ecf20Sopenharmony_ci				&vp_reg->asic_ntwk_vp_err_reg);
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci			alarm_event = VXGE_HW_SET_LEVEL(
6878c2ecf20Sopenharmony_ci				VXGE_HW_EVENT_ALARM_CLEARED, alarm_event);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci			if (skip_alarms)
6908c2ecf20Sopenharmony_ci				return VXGE_HW_OK;
6918c2ecf20Sopenharmony_ci		}
6928c2ecf20Sopenharmony_ci	}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT) {
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		pic_status = readq(&vp_reg->vpath_ppif_int_status);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci		if (pic_status &
6998c2ecf20Sopenharmony_ci		    VXGE_HW_VPATH_PPIF_INT_STATUS_GENERAL_ERRORS_GENERAL_INT) {
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci			val64 = readq(&vp_reg->general_errors_reg);
7028c2ecf20Sopenharmony_ci			mask64 = readq(&vp_reg->general_errors_mask);
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci			if ((val64 &
7058c2ecf20Sopenharmony_ci				VXGE_HW_GENERAL_ERRORS_REG_INI_SERR_DET) &
7068c2ecf20Sopenharmony_ci				~mask64) {
7078c2ecf20Sopenharmony_ci				sw_stats->error_stats.ini_serr_det++;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7108c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_SERR, alarm_event);
7118c2ecf20Sopenharmony_ci			}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci			if ((val64 &
7148c2ecf20Sopenharmony_ci			    VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO0_OVRFLOW) &
7158c2ecf20Sopenharmony_ci				~mask64) {
7168c2ecf20Sopenharmony_ci				sw_stats->error_stats.dblgen_fifo0_overflow++;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7198c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_FIFO_ERR, alarm_event);
7208c2ecf20Sopenharmony_ci			}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci			if ((val64 &
7238c2ecf20Sopenharmony_ci			    VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR) &
7248c2ecf20Sopenharmony_ci				~mask64)
7258c2ecf20Sopenharmony_ci				sw_stats->error_stats.statsb_pif_chain_error++;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci			if ((val64 &
7288c2ecf20Sopenharmony_ci			   VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ) &
7298c2ecf20Sopenharmony_ci				~mask64)
7308c2ecf20Sopenharmony_ci				sw_stats->error_stats.statsb_drop_timeout++;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci			if ((val64 &
7338c2ecf20Sopenharmony_ci				VXGE_HW_GENERAL_ERRORS_REG_TGT_ILLEGAL_ACCESS) &
7348c2ecf20Sopenharmony_ci				~mask64)
7358c2ecf20Sopenharmony_ci				sw_stats->error_stats.target_illegal_access++;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci			if (!skip_alarms) {
7388c2ecf20Sopenharmony_ci				writeq(VXGE_HW_INTR_MASK_ALL,
7398c2ecf20Sopenharmony_ci					&vp_reg->general_errors_reg);
7408c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7418c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_ALARM_CLEARED,
7428c2ecf20Sopenharmony_ci					alarm_event);
7438c2ecf20Sopenharmony_ci			}
7448c2ecf20Sopenharmony_ci		}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci		if (pic_status &
7478c2ecf20Sopenharmony_ci		    VXGE_HW_VPATH_PPIF_INT_STATUS_KDFCCTL_ERRORS_KDFCCTL_INT) {
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci			val64 = readq(&vp_reg->kdfcctl_errors_reg);
7508c2ecf20Sopenharmony_ci			mask64 = readq(&vp_reg->kdfcctl_errors_mask);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci			if ((val64 &
7538c2ecf20Sopenharmony_ci			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_OVRWR) &
7548c2ecf20Sopenharmony_ci				~mask64) {
7558c2ecf20Sopenharmony_ci				sw_stats->error_stats.kdfcctl_fifo0_overwrite++;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7588c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_FIFO_ERR,
7598c2ecf20Sopenharmony_ci					alarm_event);
7608c2ecf20Sopenharmony_ci			}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci			if ((val64 &
7638c2ecf20Sopenharmony_ci			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_POISON) &
7648c2ecf20Sopenharmony_ci				~mask64) {
7658c2ecf20Sopenharmony_ci				sw_stats->error_stats.kdfcctl_fifo0_poison++;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7688c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_FIFO_ERR,
7698c2ecf20Sopenharmony_ci					alarm_event);
7708c2ecf20Sopenharmony_ci			}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci			if ((val64 &
7738c2ecf20Sopenharmony_ci			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_DMA_ERR) &
7748c2ecf20Sopenharmony_ci				~mask64) {
7758c2ecf20Sopenharmony_ci				sw_stats->error_stats.kdfcctl_fifo0_dma_error++;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7788c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_FIFO_ERR,
7798c2ecf20Sopenharmony_ci					alarm_event);
7808c2ecf20Sopenharmony_ci			}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci			if (!skip_alarms) {
7838c2ecf20Sopenharmony_ci				writeq(VXGE_HW_INTR_MASK_ALL,
7848c2ecf20Sopenharmony_ci					&vp_reg->kdfcctl_errors_reg);
7858c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
7868c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_ALARM_CLEARED,
7878c2ecf20Sopenharmony_ci					alarm_event);
7888c2ecf20Sopenharmony_ci			}
7898c2ecf20Sopenharmony_ci		}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT) {
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->wrdma_alarm_status);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		if (val64 & VXGE_HW_WRDMA_ALARM_STATUS_PRC_ALARM_PRC_INT) {
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci			val64 = readq(&vp_reg->prc_alarm_reg);
8008c2ecf20Sopenharmony_ci			mask64 = readq(&vp_reg->prc_alarm_mask);
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP)&
8038c2ecf20Sopenharmony_ci				~mask64)
8048c2ecf20Sopenharmony_ci				sw_stats->error_stats.prc_ring_bumps++;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ERR) &
8078c2ecf20Sopenharmony_ci				~mask64) {
8088c2ecf20Sopenharmony_ci				sw_stats->error_stats.prc_rxdcm_sc_err++;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
8118c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_VPATH_ERR,
8128c2ecf20Sopenharmony_ci					alarm_event);
8138c2ecf20Sopenharmony_ci			}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ABORT)
8168c2ecf20Sopenharmony_ci				& ~mask64) {
8178c2ecf20Sopenharmony_ci				sw_stats->error_stats.prc_rxdcm_sc_abort++;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
8208c2ecf20Sopenharmony_ci						VXGE_HW_EVENT_VPATH_ERR,
8218c2ecf20Sopenharmony_ci						alarm_event);
8228c2ecf20Sopenharmony_ci			}
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_QUANTA_SIZE_ERR)
8258c2ecf20Sopenharmony_ci				 & ~mask64) {
8268c2ecf20Sopenharmony_ci				sw_stats->error_stats.prc_quanta_size_err++;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
8298c2ecf20Sopenharmony_ci					VXGE_HW_EVENT_VPATH_ERR,
8308c2ecf20Sopenharmony_ci					alarm_event);
8318c2ecf20Sopenharmony_ci			}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci			if (!skip_alarms) {
8348c2ecf20Sopenharmony_ci				writeq(VXGE_HW_INTR_MASK_ALL,
8358c2ecf20Sopenharmony_ci					&vp_reg->prc_alarm_reg);
8368c2ecf20Sopenharmony_ci				alarm_event = VXGE_HW_SET_LEVEL(
8378c2ecf20Sopenharmony_ci						VXGE_HW_EVENT_ALARM_CLEARED,
8388c2ecf20Sopenharmony_ci						alarm_event);
8398c2ecf20Sopenharmony_ci			}
8408c2ecf20Sopenharmony_ci		}
8418c2ecf20Sopenharmony_ci	}
8428c2ecf20Sopenharmony_ciout:
8438c2ecf20Sopenharmony_ci	hldev->stats.sw_dev_err_stats.vpath_alarms++;
8448c2ecf20Sopenharmony_ciout2:
8458c2ecf20Sopenharmony_ci	if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) ||
8468c2ecf20Sopenharmony_ci		(alarm_event == VXGE_HW_EVENT_UNKNOWN))
8478c2ecf20Sopenharmony_ci		return VXGE_HW_OK;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	__vxge_hw_device_handle_error(hldev, vpath->vp_id, alarm_event);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	if (alarm_event == VXGE_HW_EVENT_SERR)
8528c2ecf20Sopenharmony_ci		return VXGE_HW_ERR_CRITICAL;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	return (alarm_event == VXGE_HW_EVENT_SLOT_FREEZE) ?
8558c2ecf20Sopenharmony_ci		VXGE_HW_ERR_SLOT_FREEZE :
8568c2ecf20Sopenharmony_ci		(alarm_event == VXGE_HW_EVENT_FIFO_ERR) ? VXGE_HW_ERR_FIFO :
8578c2ecf20Sopenharmony_ci		VXGE_HW_ERR_VPATH;
8588c2ecf20Sopenharmony_ci}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci/**
8618c2ecf20Sopenharmony_ci * vxge_hw_device_begin_irq - Begin IRQ processing.
8628c2ecf20Sopenharmony_ci * @hldev: HW device handle.
8638c2ecf20Sopenharmony_ci * @skip_alarms: Do not clear the alarms
8648c2ecf20Sopenharmony_ci * @reason: "Reason" for the interrupt, the value of Titan's
8658c2ecf20Sopenharmony_ci *	general_int_status register.
8668c2ecf20Sopenharmony_ci *
8678c2ecf20Sopenharmony_ci * The function	performs two actions, It first checks whether (shared IRQ) the
8688c2ecf20Sopenharmony_ci * interrupt was raised	by the device. Next, it	masks the device interrupts.
8698c2ecf20Sopenharmony_ci *
8708c2ecf20Sopenharmony_ci * Note:
8718c2ecf20Sopenharmony_ci * vxge_hw_device_begin_irq() does not flush MMIO writes through the
8728c2ecf20Sopenharmony_ci * bridge. Therefore, two back-to-back interrupts are potentially possible.
8738c2ecf20Sopenharmony_ci *
8748c2ecf20Sopenharmony_ci * Returns: 0, if the interrupt	is not "ours" (note that in this case the
8758c2ecf20Sopenharmony_ci * device remain enabled).
8768c2ecf20Sopenharmony_ci * Otherwise, vxge_hw_device_begin_irq() returns 64bit general adapter
8778c2ecf20Sopenharmony_ci * status.
8788c2ecf20Sopenharmony_ci */
8798c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_device_begin_irq(struct __vxge_hw_device *hldev,
8808c2ecf20Sopenharmony_ci					     u32 skip_alarms, u64 *reason)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	u32 i;
8838c2ecf20Sopenharmony_ci	u64 val64;
8848c2ecf20Sopenharmony_ci	u64 adapter_status;
8858c2ecf20Sopenharmony_ci	u64 vpath_mask;
8868c2ecf20Sopenharmony_ci	enum vxge_hw_status ret = VXGE_HW_OK;
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	val64 = readq(&hldev->common_reg->titan_general_int_status);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	if (unlikely(!val64)) {
8918c2ecf20Sopenharmony_ci		/* not Titan interrupt	*/
8928c2ecf20Sopenharmony_ci		*reason	= 0;
8938c2ecf20Sopenharmony_ci		ret = VXGE_HW_ERR_WRONG_IRQ;
8948c2ecf20Sopenharmony_ci		goto exit;
8958c2ecf20Sopenharmony_ci	}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	if (unlikely(val64 == VXGE_HW_ALL_FOXES)) {
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci		adapter_status = readq(&hldev->common_reg->adapter_status);
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci		if (adapter_status == VXGE_HW_ALL_FOXES) {
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci			__vxge_hw_device_handle_error(hldev,
9048c2ecf20Sopenharmony_ci				NULL_VPID, VXGE_HW_EVENT_SLOT_FREEZE);
9058c2ecf20Sopenharmony_ci			*reason	= 0;
9068c2ecf20Sopenharmony_ci			ret = VXGE_HW_ERR_SLOT_FREEZE;
9078c2ecf20Sopenharmony_ci			goto exit;
9088c2ecf20Sopenharmony_ci		}
9098c2ecf20Sopenharmony_ci	}
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	hldev->stats.sw_dev_info_stats.total_intr_cnt++;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	*reason	= val64;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	vpath_mask = hldev->vpaths_deployed >>
9168c2ecf20Sopenharmony_ci				(64 - VXGE_HW_MAX_VIRTUAL_PATHS);
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	if (val64 &
9198c2ecf20Sopenharmony_ci	    VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_TRAFFIC_INT(vpath_mask)) {
9208c2ecf20Sopenharmony_ci		hldev->stats.sw_dev_info_stats.traffic_intr_cnt++;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci		return VXGE_HW_OK;
9238c2ecf20Sopenharmony_ci	}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	if (unlikely(val64 &
9288c2ecf20Sopenharmony_ci			VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_ALARM_INT)) {
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci		enum vxge_hw_status error_level = VXGE_HW_OK;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci		hldev->stats.sw_dev_err_stats.vpath_alarms++;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci		for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci			if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
9378c2ecf20Sopenharmony_ci				continue;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci			ret = __vxge_hw_vpath_alarm_process(
9408c2ecf20Sopenharmony_ci				&hldev->virtual_paths[i], skip_alarms);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci			error_level = VXGE_HW_SET_LEVEL(ret, error_level);
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci			if (unlikely((ret == VXGE_HW_ERR_CRITICAL) ||
9458c2ecf20Sopenharmony_ci				(ret == VXGE_HW_ERR_SLOT_FREEZE)))
9468c2ecf20Sopenharmony_ci				break;
9478c2ecf20Sopenharmony_ci		}
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci		ret = error_level;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ciexit:
9528c2ecf20Sopenharmony_ci	return ret;
9538c2ecf20Sopenharmony_ci}
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci/**
9568c2ecf20Sopenharmony_ci * vxge_hw_device_clear_tx_rx - Acknowledge (that is, clear) the
9578c2ecf20Sopenharmony_ci * condition that has caused the Tx and RX interrupt.
9588c2ecf20Sopenharmony_ci * @hldev: HW device.
9598c2ecf20Sopenharmony_ci *
9608c2ecf20Sopenharmony_ci * Acknowledge (that is, clear) the condition that has caused
9618c2ecf20Sopenharmony_ci * the Tx and Rx interrupt.
9628c2ecf20Sopenharmony_ci * See also: vxge_hw_device_begin_irq(),
9638c2ecf20Sopenharmony_ci * vxge_hw_device_mask_tx_rx(), vxge_hw_device_unmask_tx_rx().
9648c2ecf20Sopenharmony_ci */
9658c2ecf20Sopenharmony_civoid vxge_hw_device_clear_tx_rx(struct __vxge_hw_device *hldev)
9668c2ecf20Sopenharmony_ci{
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	if ((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
9698c2ecf20Sopenharmony_ci	   (hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
9708c2ecf20Sopenharmony_ci		writeq((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
9718c2ecf20Sopenharmony_ci				 hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX]),
9728c2ecf20Sopenharmony_ci				&hldev->common_reg->tim_int_status0);
9738c2ecf20Sopenharmony_ci	}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	if ((hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
9768c2ecf20Sopenharmony_ci	   (hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
9778c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper(
9788c2ecf20Sopenharmony_ci				(hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
9798c2ecf20Sopenharmony_ci				 hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX]),
9808c2ecf20Sopenharmony_ci				&hldev->common_reg->tim_int_status1);
9818c2ecf20Sopenharmony_ci	}
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci/*
9858c2ecf20Sopenharmony_ci * vxge_hw_channel_dtr_alloc - Allocate a dtr from the channel
9868c2ecf20Sopenharmony_ci * @channel: Channel
9878c2ecf20Sopenharmony_ci * @dtrh: Buffer to return the DTR pointer
9888c2ecf20Sopenharmony_ci *
9898c2ecf20Sopenharmony_ci * Allocates a dtr from the reserve array. If the reserve array is empty,
9908c2ecf20Sopenharmony_ci * it swaps the reserve and free arrays.
9918c2ecf20Sopenharmony_ci *
9928c2ecf20Sopenharmony_ci */
9938c2ecf20Sopenharmony_cistatic enum vxge_hw_status
9948c2ecf20Sopenharmony_civxge_hw_channel_dtr_alloc(struct __vxge_hw_channel *channel, void **dtrh)
9958c2ecf20Sopenharmony_ci{
9968c2ecf20Sopenharmony_ci	if (channel->reserve_ptr - channel->reserve_top > 0) {
9978c2ecf20Sopenharmony_ci_alloc_after_swap:
9988c2ecf20Sopenharmony_ci		*dtrh =	channel->reserve_arr[--channel->reserve_ptr];
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci		return VXGE_HW_OK;
10018c2ecf20Sopenharmony_ci	}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	/* switch between empty	and full arrays	*/
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	/* the idea behind such	a design is that by having free	and reserved
10068c2ecf20Sopenharmony_ci	 * arrays separated we basically separated irq and non-irq parts.
10078c2ecf20Sopenharmony_ci	 * i.e.	no additional lock need	to be done when	we free	a resource */
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	if (channel->length - channel->free_ptr > 0) {
10108c2ecf20Sopenharmony_ci		swap(channel->reserve_arr, channel->free_arr);
10118c2ecf20Sopenharmony_ci		channel->reserve_ptr = channel->length;
10128c2ecf20Sopenharmony_ci		channel->reserve_top = channel->free_ptr;
10138c2ecf20Sopenharmony_ci		channel->free_ptr = channel->length;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci		channel->stats->reserve_free_swaps_cnt++;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci		goto _alloc_after_swap;
10188c2ecf20Sopenharmony_ci	}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	channel->stats->full_cnt++;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	*dtrh =	NULL;
10238c2ecf20Sopenharmony_ci	return VXGE_HW_INF_OUT_OF_DESCRIPTORS;
10248c2ecf20Sopenharmony_ci}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci/*
10278c2ecf20Sopenharmony_ci * vxge_hw_channel_dtr_post - Post a dtr to the channel
10288c2ecf20Sopenharmony_ci * @channelh: Channel
10298c2ecf20Sopenharmony_ci * @dtrh: DTR pointer
10308c2ecf20Sopenharmony_ci *
10318c2ecf20Sopenharmony_ci * Posts a dtr to work array.
10328c2ecf20Sopenharmony_ci *
10338c2ecf20Sopenharmony_ci */
10348c2ecf20Sopenharmony_cistatic void
10358c2ecf20Sopenharmony_civxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel, void *dtrh)
10368c2ecf20Sopenharmony_ci{
10378c2ecf20Sopenharmony_ci	vxge_assert(channel->work_arr[channel->post_index] == NULL);
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	channel->work_arr[channel->post_index++] = dtrh;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	/* wrap-around */
10428c2ecf20Sopenharmony_ci	if (channel->post_index	== channel->length)
10438c2ecf20Sopenharmony_ci		channel->post_index = 0;
10448c2ecf20Sopenharmony_ci}
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci/*
10478c2ecf20Sopenharmony_ci * vxge_hw_channel_dtr_try_complete - Returns next completed dtr
10488c2ecf20Sopenharmony_ci * @channel: Channel
10498c2ecf20Sopenharmony_ci * @dtr: Buffer to return the next completed DTR pointer
10508c2ecf20Sopenharmony_ci *
10518c2ecf20Sopenharmony_ci * Returns the next completed dtr with out removing it from work array
10528c2ecf20Sopenharmony_ci *
10538c2ecf20Sopenharmony_ci */
10548c2ecf20Sopenharmony_civoid
10558c2ecf20Sopenharmony_civxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel, void **dtrh)
10568c2ecf20Sopenharmony_ci{
10578c2ecf20Sopenharmony_ci	vxge_assert(channel->compl_index < channel->length);
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	*dtrh =	channel->work_arr[channel->compl_index];
10608c2ecf20Sopenharmony_ci	prefetch(*dtrh);
10618c2ecf20Sopenharmony_ci}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci/*
10648c2ecf20Sopenharmony_ci * vxge_hw_channel_dtr_complete - Removes next completed dtr from the work array
10658c2ecf20Sopenharmony_ci * @channel: Channel handle
10668c2ecf20Sopenharmony_ci *
10678c2ecf20Sopenharmony_ci * Removes the next completed dtr from work array
10688c2ecf20Sopenharmony_ci *
10698c2ecf20Sopenharmony_ci */
10708c2ecf20Sopenharmony_civoid vxge_hw_channel_dtr_complete(struct __vxge_hw_channel *channel)
10718c2ecf20Sopenharmony_ci{
10728c2ecf20Sopenharmony_ci	channel->work_arr[channel->compl_index]	= NULL;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	/* wrap-around */
10758c2ecf20Sopenharmony_ci	if (++channel->compl_index == channel->length)
10768c2ecf20Sopenharmony_ci		channel->compl_index = 0;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	channel->stats->total_compl_cnt++;
10798c2ecf20Sopenharmony_ci}
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci/*
10828c2ecf20Sopenharmony_ci * vxge_hw_channel_dtr_free - Frees a dtr
10838c2ecf20Sopenharmony_ci * @channel: Channel handle
10848c2ecf20Sopenharmony_ci * @dtr:  DTR pointer
10858c2ecf20Sopenharmony_ci *
10868c2ecf20Sopenharmony_ci * Returns the dtr to free array
10878c2ecf20Sopenharmony_ci *
10888c2ecf20Sopenharmony_ci */
10898c2ecf20Sopenharmony_civoid vxge_hw_channel_dtr_free(struct __vxge_hw_channel *channel, void *dtrh)
10908c2ecf20Sopenharmony_ci{
10918c2ecf20Sopenharmony_ci	channel->free_arr[--channel->free_ptr] = dtrh;
10928c2ecf20Sopenharmony_ci}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci/*
10958c2ecf20Sopenharmony_ci * vxge_hw_channel_dtr_count
10968c2ecf20Sopenharmony_ci * @channel: Channel handle. Obtained via vxge_hw_channel_open().
10978c2ecf20Sopenharmony_ci *
10988c2ecf20Sopenharmony_ci * Retrieve number of DTRs available. This function can not be called
10998c2ecf20Sopenharmony_ci * from data path. ring_initial_replenishi() is the only user.
11008c2ecf20Sopenharmony_ci */
11018c2ecf20Sopenharmony_ciint vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel)
11028c2ecf20Sopenharmony_ci{
11038c2ecf20Sopenharmony_ci	return (channel->reserve_ptr - channel->reserve_top) +
11048c2ecf20Sopenharmony_ci		(channel->length - channel->free_ptr);
11058c2ecf20Sopenharmony_ci}
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci/**
11088c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_reserve	- Reserve ring descriptor.
11098c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
11108c2ecf20Sopenharmony_ci * @rxdh: Reserved descriptor. On success HW fills this "out" parameter
11118c2ecf20Sopenharmony_ci * with a valid handle.
11128c2ecf20Sopenharmony_ci *
11138c2ecf20Sopenharmony_ci * Reserve Rx descriptor for the subsequent filling-in driver
11148c2ecf20Sopenharmony_ci * and posting on the corresponding channel (@channelh)
11158c2ecf20Sopenharmony_ci * via vxge_hw_ring_rxd_post().
11168c2ecf20Sopenharmony_ci *
11178c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK - success.
11188c2ecf20Sopenharmony_ci * VXGE_HW_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available.
11198c2ecf20Sopenharmony_ci *
11208c2ecf20Sopenharmony_ci */
11218c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_ring_rxd_reserve(struct __vxge_hw_ring *ring,
11228c2ecf20Sopenharmony_ci	void **rxdh)
11238c2ecf20Sopenharmony_ci{
11248c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
11258c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	channel = &ring->channel;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	status = vxge_hw_channel_dtr_alloc(channel, rxdh);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	if (status == VXGE_HW_OK) {
11328c2ecf20Sopenharmony_ci		struct vxge_hw_ring_rxd_1 *rxdp =
11338c2ecf20Sopenharmony_ci			(struct vxge_hw_ring_rxd_1 *)*rxdh;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci		rxdp->control_0	= rxdp->control_1 = 0;
11368c2ecf20Sopenharmony_ci	}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	return status;
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci/**
11428c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_free - Free descriptor.
11438c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
11448c2ecf20Sopenharmony_ci * @rxdh: Descriptor handle.
11458c2ecf20Sopenharmony_ci *
11468c2ecf20Sopenharmony_ci * Free	the reserved descriptor. This operation is "symmetrical" to
11478c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_reserve. The "free-ing" completes the descriptor's
11488c2ecf20Sopenharmony_ci * lifecycle.
11498c2ecf20Sopenharmony_ci *
11508c2ecf20Sopenharmony_ci * After free-ing (see vxge_hw_ring_rxd_free()) the descriptor again can
11518c2ecf20Sopenharmony_ci * be:
11528c2ecf20Sopenharmony_ci *
11538c2ecf20Sopenharmony_ci * - reserved (vxge_hw_ring_rxd_reserve);
11548c2ecf20Sopenharmony_ci *
11558c2ecf20Sopenharmony_ci * - posted	(vxge_hw_ring_rxd_post);
11568c2ecf20Sopenharmony_ci *
11578c2ecf20Sopenharmony_ci * - completed (vxge_hw_ring_rxd_next_completed);
11588c2ecf20Sopenharmony_ci *
11598c2ecf20Sopenharmony_ci * - and recycled again	(vxge_hw_ring_rxd_free).
11608c2ecf20Sopenharmony_ci *
11618c2ecf20Sopenharmony_ci * For alternative state transitions and more details please refer to
11628c2ecf20Sopenharmony_ci * the design doc.
11638c2ecf20Sopenharmony_ci *
11648c2ecf20Sopenharmony_ci */
11658c2ecf20Sopenharmony_civoid vxge_hw_ring_rxd_free(struct __vxge_hw_ring *ring, void *rxdh)
11668c2ecf20Sopenharmony_ci{
11678c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	channel = &ring->channel;
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_free(channel, rxdh);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci}
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci/**
11768c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_pre_post - Prepare rxd and post
11778c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
11788c2ecf20Sopenharmony_ci * @rxdh: Descriptor handle.
11798c2ecf20Sopenharmony_ci *
11808c2ecf20Sopenharmony_ci * This routine prepares a rxd and posts
11818c2ecf20Sopenharmony_ci */
11828c2ecf20Sopenharmony_civoid vxge_hw_ring_rxd_pre_post(struct __vxge_hw_ring *ring, void *rxdh)
11838c2ecf20Sopenharmony_ci{
11848c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	channel = &ring->channel;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_post(channel, rxdh);
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci/**
11928c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_post_post - Process rxd after post.
11938c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
11948c2ecf20Sopenharmony_ci * @rxdh: Descriptor handle.
11958c2ecf20Sopenharmony_ci *
11968c2ecf20Sopenharmony_ci * Processes rxd after post
11978c2ecf20Sopenharmony_ci */
11988c2ecf20Sopenharmony_civoid vxge_hw_ring_rxd_post_post(struct __vxge_hw_ring *ring, void *rxdh)
11998c2ecf20Sopenharmony_ci{
12008c2ecf20Sopenharmony_ci	struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	rxdp->control_0	= VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	if (ring->stats->common_stats.usage_cnt > 0)
12058c2ecf20Sopenharmony_ci		ring->stats->common_stats.usage_cnt--;
12068c2ecf20Sopenharmony_ci}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci/**
12098c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_post - Post descriptor on the ring.
12108c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
12118c2ecf20Sopenharmony_ci * @rxdh: Descriptor obtained via vxge_hw_ring_rxd_reserve().
12128c2ecf20Sopenharmony_ci *
12138c2ecf20Sopenharmony_ci * Post	descriptor on the ring.
12148c2ecf20Sopenharmony_ci * Prior to posting the	descriptor should be filled in accordance with
12158c2ecf20Sopenharmony_ci * Host/Titan interface specification for a given service (LL, etc.).
12168c2ecf20Sopenharmony_ci *
12178c2ecf20Sopenharmony_ci */
12188c2ecf20Sopenharmony_civoid vxge_hw_ring_rxd_post(struct __vxge_hw_ring *ring, void *rxdh)
12198c2ecf20Sopenharmony_ci{
12208c2ecf20Sopenharmony_ci	struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh;
12218c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	channel = &ring->channel;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	wmb();
12268c2ecf20Sopenharmony_ci	rxdp->control_0	= VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_post(channel, rxdh);
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (ring->stats->common_stats.usage_cnt > 0)
12318c2ecf20Sopenharmony_ci		ring->stats->common_stats.usage_cnt--;
12328c2ecf20Sopenharmony_ci}
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci/**
12358c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_post_post_wmb - Process rxd after post with memory barrier.
12368c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
12378c2ecf20Sopenharmony_ci * @rxdh: Descriptor handle.
12388c2ecf20Sopenharmony_ci *
12398c2ecf20Sopenharmony_ci * Processes rxd after post with memory barrier.
12408c2ecf20Sopenharmony_ci */
12418c2ecf20Sopenharmony_civoid vxge_hw_ring_rxd_post_post_wmb(struct __vxge_hw_ring *ring, void *rxdh)
12428c2ecf20Sopenharmony_ci{
12438c2ecf20Sopenharmony_ci	wmb();
12448c2ecf20Sopenharmony_ci	vxge_hw_ring_rxd_post_post(ring, rxdh);
12458c2ecf20Sopenharmony_ci}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci/**
12488c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_next_completed - Get the _next_ completed descriptor.
12498c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
12508c2ecf20Sopenharmony_ci * @rxdh: Descriptor handle. Returned by HW.
12518c2ecf20Sopenharmony_ci * @t_code:	Transfer code, as per Titan User Guide,
12528c2ecf20Sopenharmony_ci *	 Receive Descriptor Format. Returned by HW.
12538c2ecf20Sopenharmony_ci *
12548c2ecf20Sopenharmony_ci * Retrieve the	_next_ completed descriptor.
12558c2ecf20Sopenharmony_ci * HW uses ring callback (*vxge_hw_ring_callback_f) to notifiy
12568c2ecf20Sopenharmony_ci * driver of new completed descriptors. After that
12578c2ecf20Sopenharmony_ci * the driver can use vxge_hw_ring_rxd_next_completed to retrieve the rest
12588c2ecf20Sopenharmony_ci * completions (the very first completion is passed by HW via
12598c2ecf20Sopenharmony_ci * vxge_hw_ring_callback_f).
12608c2ecf20Sopenharmony_ci *
12618c2ecf20Sopenharmony_ci * Implementation-wise, the driver is free to call
12628c2ecf20Sopenharmony_ci * vxge_hw_ring_rxd_next_completed either immediately from inside the
12638c2ecf20Sopenharmony_ci * ring callback, or in a deferred fashion and separate (from HW)
12648c2ecf20Sopenharmony_ci * context.
12658c2ecf20Sopenharmony_ci *
12668c2ecf20Sopenharmony_ci * Non-zero @t_code means failure to fill-in receive buffer(s)
12678c2ecf20Sopenharmony_ci * of the descriptor.
12688c2ecf20Sopenharmony_ci * For instance, parity	error detected during the data transfer.
12698c2ecf20Sopenharmony_ci * In this case	Titan will complete the descriptor and indicate
12708c2ecf20Sopenharmony_ci * for the host	that the received data is not to be used.
12718c2ecf20Sopenharmony_ci * For details please refer to Titan User Guide.
12728c2ecf20Sopenharmony_ci *
12738c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK - success.
12748c2ecf20Sopenharmony_ci * VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
12758c2ecf20Sopenharmony_ci * are currently available for processing.
12768c2ecf20Sopenharmony_ci *
12778c2ecf20Sopenharmony_ci * See also: vxge_hw_ring_callback_f{},
12788c2ecf20Sopenharmony_ci * vxge_hw_fifo_rxd_next_completed(), enum vxge_hw_status{}.
12798c2ecf20Sopenharmony_ci */
12808c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_ring_rxd_next_completed(
12818c2ecf20Sopenharmony_ci	struct __vxge_hw_ring *ring, void **rxdh, u8 *t_code)
12828c2ecf20Sopenharmony_ci{
12838c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
12848c2ecf20Sopenharmony_ci	struct vxge_hw_ring_rxd_1 *rxdp;
12858c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
12868c2ecf20Sopenharmony_ci	u64 control_0, own;
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	channel = &ring->channel;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_try_complete(channel, rxdh);
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	rxdp = *rxdh;
12938c2ecf20Sopenharmony_ci	if (rxdp == NULL) {
12948c2ecf20Sopenharmony_ci		status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
12958c2ecf20Sopenharmony_ci		goto exit;
12968c2ecf20Sopenharmony_ci	}
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci	control_0 = rxdp->control_0;
12998c2ecf20Sopenharmony_ci	own = control_0 & VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
13008c2ecf20Sopenharmony_ci	*t_code	= (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0);
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	/* check whether it is not the end */
13038c2ecf20Sopenharmony_ci	if (!own || *t_code == VXGE_HW_RING_T_CODE_FRM_DROP) {
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci		vxge_assert((rxdp)->host_control !=
13068c2ecf20Sopenharmony_ci				0);
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci		++ring->cmpl_cnt;
13098c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_complete(channel);
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci		vxge_assert(*t_code != VXGE_HW_RING_RXD_T_CODE_UNUSED);
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		ring->stats->common_stats.usage_cnt++;
13148c2ecf20Sopenharmony_ci		if (ring->stats->common_stats.usage_max <
13158c2ecf20Sopenharmony_ci				ring->stats->common_stats.usage_cnt)
13168c2ecf20Sopenharmony_ci			ring->stats->common_stats.usage_max =
13178c2ecf20Sopenharmony_ci				ring->stats->common_stats.usage_cnt;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci		status = VXGE_HW_OK;
13208c2ecf20Sopenharmony_ci		goto exit;
13218c2ecf20Sopenharmony_ci	}
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	/* reset it. since we don't want to return
13248c2ecf20Sopenharmony_ci	 * garbage to the driver */
13258c2ecf20Sopenharmony_ci	*rxdh =	NULL;
13268c2ecf20Sopenharmony_ci	status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
13278c2ecf20Sopenharmony_ciexit:
13288c2ecf20Sopenharmony_ci	return status;
13298c2ecf20Sopenharmony_ci}
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci/**
13328c2ecf20Sopenharmony_ci * vxge_hw_ring_handle_tcode - Handle transfer code.
13338c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
13348c2ecf20Sopenharmony_ci * @rxdh: Descriptor handle.
13358c2ecf20Sopenharmony_ci * @t_code: One of the enumerated (and documented in the Titan user guide)
13368c2ecf20Sopenharmony_ci * "transfer codes".
13378c2ecf20Sopenharmony_ci *
13388c2ecf20Sopenharmony_ci * Handle descriptor's transfer code. The latter comes with each completed
13398c2ecf20Sopenharmony_ci * descriptor.
13408c2ecf20Sopenharmony_ci *
13418c2ecf20Sopenharmony_ci * Returns: one of the enum vxge_hw_status{} enumerated types.
13428c2ecf20Sopenharmony_ci * VXGE_HW_OK			- for success.
13438c2ecf20Sopenharmony_ci * VXGE_HW_ERR_CRITICAL         - when encounters critical error.
13448c2ecf20Sopenharmony_ci */
13458c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_ring_handle_tcode(
13468c2ecf20Sopenharmony_ci	struct __vxge_hw_ring *ring, void *rxdh, u8 t_code)
13478c2ecf20Sopenharmony_ci{
13488c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	/* If the t_code is not supported and if the
13518c2ecf20Sopenharmony_ci	 * t_code is other than 0x5 (unparseable packet
13528c2ecf20Sopenharmony_ci	 * such as unknown UPV6 header), Drop it !!!
13538c2ecf20Sopenharmony_ci	 */
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	if (t_code ==  VXGE_HW_RING_T_CODE_OK ||
13568c2ecf20Sopenharmony_ci		t_code == VXGE_HW_RING_T_CODE_L3_PKT_ERR) {
13578c2ecf20Sopenharmony_ci		status = VXGE_HW_OK;
13588c2ecf20Sopenharmony_ci		goto exit;
13598c2ecf20Sopenharmony_ci	}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	if (t_code > VXGE_HW_RING_T_CODE_MULTI_ERR) {
13628c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_TCODE;
13638c2ecf20Sopenharmony_ci		goto exit;
13648c2ecf20Sopenharmony_ci	}
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	ring->stats->rxd_t_code_err_cnt[t_code]++;
13678c2ecf20Sopenharmony_ciexit:
13688c2ecf20Sopenharmony_ci	return status;
13698c2ecf20Sopenharmony_ci}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci/**
13728c2ecf20Sopenharmony_ci * __vxge_hw_non_offload_db_post - Post non offload doorbell
13738c2ecf20Sopenharmony_ci *
13748c2ecf20Sopenharmony_ci * @fifo: fifohandle
13758c2ecf20Sopenharmony_ci * @txdl_ptr: The starting location of the TxDL in host memory
13768c2ecf20Sopenharmony_ci * @num_txds: The highest TxD in this TxDL (0 to 255 means 1 to 256)
13778c2ecf20Sopenharmony_ci * @no_snoop: No snoop flags
13788c2ecf20Sopenharmony_ci *
13798c2ecf20Sopenharmony_ci * This function posts a non-offload doorbell to doorbell FIFO
13808c2ecf20Sopenharmony_ci *
13818c2ecf20Sopenharmony_ci */
13828c2ecf20Sopenharmony_cistatic void __vxge_hw_non_offload_db_post(struct __vxge_hw_fifo *fifo,
13838c2ecf20Sopenharmony_ci	u64 txdl_ptr, u32 num_txds, u32 no_snoop)
13848c2ecf20Sopenharmony_ci{
13858c2ecf20Sopenharmony_ci	writeq(VXGE_HW_NODBW_TYPE(VXGE_HW_NODBW_TYPE_NODBW) |
13868c2ecf20Sopenharmony_ci		VXGE_HW_NODBW_LAST_TXD_NUMBER(num_txds) |
13878c2ecf20Sopenharmony_ci		VXGE_HW_NODBW_GET_NO_SNOOP(no_snoop),
13888c2ecf20Sopenharmony_ci		&fifo->nofl_db->control_0);
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	writeq(txdl_ptr, &fifo->nofl_db->txdl_ptr);
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci/**
13948c2ecf20Sopenharmony_ci * vxge_hw_fifo_free_txdl_count_get - returns the number of txdls available in
13958c2ecf20Sopenharmony_ci * the fifo
13968c2ecf20Sopenharmony_ci * @fifoh: Handle to the fifo object used for non offload send
13978c2ecf20Sopenharmony_ci */
13988c2ecf20Sopenharmony_ciu32 vxge_hw_fifo_free_txdl_count_get(struct __vxge_hw_fifo *fifoh)
13998c2ecf20Sopenharmony_ci{
14008c2ecf20Sopenharmony_ci	return vxge_hw_channel_dtr_count(&fifoh->channel);
14018c2ecf20Sopenharmony_ci}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci/**
14048c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_reserve - Reserve fifo descriptor.
14058c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
14068c2ecf20Sopenharmony_ci * @txdlh: Reserved descriptor. On success HW fills this "out" parameter
14078c2ecf20Sopenharmony_ci *        with a valid handle.
14088c2ecf20Sopenharmony_ci * @txdl_priv: Buffer to return the pointer to per txdl space
14098c2ecf20Sopenharmony_ci *
14108c2ecf20Sopenharmony_ci * Reserve a single TxDL (that is, fifo descriptor)
14118c2ecf20Sopenharmony_ci * for the subsequent filling-in by driver)
14128c2ecf20Sopenharmony_ci * and posting on the corresponding channel (@channelh)
14138c2ecf20Sopenharmony_ci * via vxge_hw_fifo_txdl_post().
14148c2ecf20Sopenharmony_ci *
14158c2ecf20Sopenharmony_ci * Note: it is the responsibility of driver to reserve multiple descriptors
14168c2ecf20Sopenharmony_ci * for lengthy (e.g., LSO) transmit operation. A single fifo descriptor
14178c2ecf20Sopenharmony_ci * carries up to configured number (fifo.max_frags) of contiguous buffers.
14188c2ecf20Sopenharmony_ci *
14198c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK - success;
14208c2ecf20Sopenharmony_ci * VXGE_HW_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available
14218c2ecf20Sopenharmony_ci *
14228c2ecf20Sopenharmony_ci */
14238c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_fifo_txdl_reserve(
14248c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo *fifo,
14258c2ecf20Sopenharmony_ci	void **txdlh, void **txdl_priv)
14268c2ecf20Sopenharmony_ci{
14278c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
14288c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
14298c2ecf20Sopenharmony_ci	int i;
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	channel = &fifo->channel;
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci	status = vxge_hw_channel_dtr_alloc(channel, txdlh);
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	if (status == VXGE_HW_OK) {
14368c2ecf20Sopenharmony_ci		struct vxge_hw_fifo_txd *txdp =
14378c2ecf20Sopenharmony_ci			(struct vxge_hw_fifo_txd *)*txdlh;
14388c2ecf20Sopenharmony_ci		struct __vxge_hw_fifo_txdl_priv *priv;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci		priv = __vxge_hw_fifo_txdl_priv(fifo, txdp);
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci		/* reset the TxDL's private */
14438c2ecf20Sopenharmony_ci		priv->align_dma_offset = 0;
14448c2ecf20Sopenharmony_ci		priv->align_vaddr_start = priv->align_vaddr;
14458c2ecf20Sopenharmony_ci		priv->align_used_frags = 0;
14468c2ecf20Sopenharmony_ci		priv->frags = 0;
14478c2ecf20Sopenharmony_ci		priv->alloc_frags = fifo->config->max_frags;
14488c2ecf20Sopenharmony_ci		priv->next_txdl_priv = NULL;
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci		*txdl_priv = (void *)(size_t)txdp->host_control;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci		for (i = 0; i < fifo->config->max_frags; i++) {
14538c2ecf20Sopenharmony_ci			txdp = ((struct vxge_hw_fifo_txd *)*txdlh) + i;
14548c2ecf20Sopenharmony_ci			txdp->control_0 = txdp->control_1 = 0;
14558c2ecf20Sopenharmony_ci		}
14568c2ecf20Sopenharmony_ci	}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	return status;
14598c2ecf20Sopenharmony_ci}
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci/**
14628c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_buffer_set - Set transmit buffer pointer in the
14638c2ecf20Sopenharmony_ci * descriptor.
14648c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
14658c2ecf20Sopenharmony_ci * @txdlh: Descriptor handle.
14668c2ecf20Sopenharmony_ci * @frag_idx: Index of the data buffer in the caller's scatter-gather list
14678c2ecf20Sopenharmony_ci *            (of buffers).
14688c2ecf20Sopenharmony_ci * @dma_pointer: DMA address of the data buffer referenced by @frag_idx.
14698c2ecf20Sopenharmony_ci * @size: Size of the data buffer (in bytes).
14708c2ecf20Sopenharmony_ci *
14718c2ecf20Sopenharmony_ci * This API is part of the preparation of the transmit descriptor for posting
14728c2ecf20Sopenharmony_ci * (via vxge_hw_fifo_txdl_post()). The related "preparation" APIs include
14738c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_mss_set() and vxge_hw_fifo_txdl_cksum_set_bits().
14748c2ecf20Sopenharmony_ci * All three APIs fill in the fields of the fifo descriptor,
14758c2ecf20Sopenharmony_ci * in accordance with the Titan specification.
14768c2ecf20Sopenharmony_ci *
14778c2ecf20Sopenharmony_ci */
14788c2ecf20Sopenharmony_civoid vxge_hw_fifo_txdl_buffer_set(struct __vxge_hw_fifo *fifo,
14798c2ecf20Sopenharmony_ci				  void *txdlh, u32 frag_idx,
14808c2ecf20Sopenharmony_ci				  dma_addr_t dma_pointer, u32 size)
14818c2ecf20Sopenharmony_ci{
14828c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo_txdl_priv *txdl_priv;
14838c2ecf20Sopenharmony_ci	struct vxge_hw_fifo_txd *txdp, *txdp_last;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
14868c2ecf20Sopenharmony_ci	txdp = (struct vxge_hw_fifo_txd *)txdlh  +  txdl_priv->frags;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	if (frag_idx != 0)
14898c2ecf20Sopenharmony_ci		txdp->control_0 = txdp->control_1 = 0;
14908c2ecf20Sopenharmony_ci	else {
14918c2ecf20Sopenharmony_ci		txdp->control_0 |= VXGE_HW_FIFO_TXD_GATHER_CODE(
14928c2ecf20Sopenharmony_ci			VXGE_HW_FIFO_TXD_GATHER_CODE_FIRST);
14938c2ecf20Sopenharmony_ci		txdp->control_1 |= fifo->interrupt_type;
14948c2ecf20Sopenharmony_ci		txdp->control_1 |= VXGE_HW_FIFO_TXD_INT_NUMBER(
14958c2ecf20Sopenharmony_ci			fifo->tx_intr_num);
14968c2ecf20Sopenharmony_ci		if (txdl_priv->frags) {
14978c2ecf20Sopenharmony_ci			txdp_last = (struct vxge_hw_fifo_txd *)txdlh  +
14988c2ecf20Sopenharmony_ci			(txdl_priv->frags - 1);
14998c2ecf20Sopenharmony_ci			txdp_last->control_0 |= VXGE_HW_FIFO_TXD_GATHER_CODE(
15008c2ecf20Sopenharmony_ci				VXGE_HW_FIFO_TXD_GATHER_CODE_LAST);
15018c2ecf20Sopenharmony_ci		}
15028c2ecf20Sopenharmony_ci	}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	vxge_assert(frag_idx < txdl_priv->alloc_frags);
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	txdp->buffer_pointer = (u64)dma_pointer;
15078c2ecf20Sopenharmony_ci	txdp->control_0 |= VXGE_HW_FIFO_TXD_BUFFER_SIZE(size);
15088c2ecf20Sopenharmony_ci	fifo->stats->total_buffers++;
15098c2ecf20Sopenharmony_ci	txdl_priv->frags++;
15108c2ecf20Sopenharmony_ci}
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci/**
15138c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_post - Post descriptor on the fifo channel.
15148c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
15158c2ecf20Sopenharmony_ci * @txdlh: Descriptor obtained via vxge_hw_fifo_txdl_reserve()
15168c2ecf20Sopenharmony_ci *
15178c2ecf20Sopenharmony_ci * Post descriptor on the 'fifo' type channel for transmission.
15188c2ecf20Sopenharmony_ci * Prior to posting the descriptor should be filled in accordance with
15198c2ecf20Sopenharmony_ci * Host/Titan interface specification for a given service (LL, etc.).
15208c2ecf20Sopenharmony_ci *
15218c2ecf20Sopenharmony_ci */
15228c2ecf20Sopenharmony_civoid vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo, void *txdlh)
15238c2ecf20Sopenharmony_ci{
15248c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo_txdl_priv *txdl_priv;
15258c2ecf20Sopenharmony_ci	struct vxge_hw_fifo_txd *txdp_last;
15268c2ecf20Sopenharmony_ci	struct vxge_hw_fifo_txd *txdp_first;
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
15298c2ecf20Sopenharmony_ci	txdp_first = txdlh;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	txdp_last = (struct vxge_hw_fifo_txd *)txdlh  +  (txdl_priv->frags - 1);
15328c2ecf20Sopenharmony_ci	txdp_last->control_0 |=
15338c2ecf20Sopenharmony_ci	      VXGE_HW_FIFO_TXD_GATHER_CODE(VXGE_HW_FIFO_TXD_GATHER_CODE_LAST);
15348c2ecf20Sopenharmony_ci	txdp_first->control_0 |= VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER;
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_post(&fifo->channel, txdlh);
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	__vxge_hw_non_offload_db_post(fifo,
15398c2ecf20Sopenharmony_ci		(u64)txdl_priv->dma_addr,
15408c2ecf20Sopenharmony_ci		txdl_priv->frags - 1,
15418c2ecf20Sopenharmony_ci		fifo->no_snoop_bits);
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	fifo->stats->total_posts++;
15448c2ecf20Sopenharmony_ci	fifo->stats->common_stats.usage_cnt++;
15458c2ecf20Sopenharmony_ci	if (fifo->stats->common_stats.usage_max <
15468c2ecf20Sopenharmony_ci		fifo->stats->common_stats.usage_cnt)
15478c2ecf20Sopenharmony_ci		fifo->stats->common_stats.usage_max =
15488c2ecf20Sopenharmony_ci			fifo->stats->common_stats.usage_cnt;
15498c2ecf20Sopenharmony_ci}
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci/**
15528c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_next_completed - Retrieve next completed descriptor.
15538c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
15548c2ecf20Sopenharmony_ci * @txdlh: Descriptor handle. Returned by HW.
15558c2ecf20Sopenharmony_ci * @t_code: Transfer code, as per Titan User Guide,
15568c2ecf20Sopenharmony_ci *          Transmit Descriptor Format.
15578c2ecf20Sopenharmony_ci *          Returned by HW.
15588c2ecf20Sopenharmony_ci *
15598c2ecf20Sopenharmony_ci * Retrieve the _next_ completed descriptor.
15608c2ecf20Sopenharmony_ci * HW uses channel callback (*vxge_hw_channel_callback_f) to notifiy
15618c2ecf20Sopenharmony_ci * driver of new completed descriptors. After that
15628c2ecf20Sopenharmony_ci * the driver can use vxge_hw_fifo_txdl_next_completed to retrieve the rest
15638c2ecf20Sopenharmony_ci * completions (the very first completion is passed by HW via
15648c2ecf20Sopenharmony_ci * vxge_hw_channel_callback_f).
15658c2ecf20Sopenharmony_ci *
15668c2ecf20Sopenharmony_ci * Implementation-wise, the driver is free to call
15678c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_next_completed either immediately from inside the
15688c2ecf20Sopenharmony_ci * channel callback, or in a deferred fashion and separate (from HW)
15698c2ecf20Sopenharmony_ci * context.
15708c2ecf20Sopenharmony_ci *
15718c2ecf20Sopenharmony_ci * Non-zero @t_code means failure to process the descriptor.
15728c2ecf20Sopenharmony_ci * The failure could happen, for instance, when the link is
15738c2ecf20Sopenharmony_ci * down, in which case Titan completes the descriptor because it
15748c2ecf20Sopenharmony_ci * is not able to send the data out.
15758c2ecf20Sopenharmony_ci *
15768c2ecf20Sopenharmony_ci * For details please refer to Titan User Guide.
15778c2ecf20Sopenharmony_ci *
15788c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK - success.
15798c2ecf20Sopenharmony_ci * VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
15808c2ecf20Sopenharmony_ci * are currently available for processing.
15818c2ecf20Sopenharmony_ci *
15828c2ecf20Sopenharmony_ci */
15838c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_fifo_txdl_next_completed(
15848c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo *fifo, void **txdlh,
15858c2ecf20Sopenharmony_ci	enum vxge_hw_fifo_tcode *t_code)
15868c2ecf20Sopenharmony_ci{
15878c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
15888c2ecf20Sopenharmony_ci	struct vxge_hw_fifo_txd *txdp;
15898c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	channel = &fifo->channel;
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_try_complete(channel, txdlh);
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	txdp = *txdlh;
15968c2ecf20Sopenharmony_ci	if (txdp == NULL) {
15978c2ecf20Sopenharmony_ci		status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
15988c2ecf20Sopenharmony_ci		goto exit;
15998c2ecf20Sopenharmony_ci	}
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	/* check whether host owns it */
16028c2ecf20Sopenharmony_ci	if (!(txdp->control_0 & VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER)) {
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci		vxge_assert(txdp->host_control != 0);
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_complete(channel);
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci		*t_code = (u8)VXGE_HW_FIFO_TXD_T_CODE_GET(txdp->control_0);
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci		if (fifo->stats->common_stats.usage_cnt > 0)
16118c2ecf20Sopenharmony_ci			fifo->stats->common_stats.usage_cnt--;
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci		status = VXGE_HW_OK;
16148c2ecf20Sopenharmony_ci		goto exit;
16158c2ecf20Sopenharmony_ci	}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	/* no more completions */
16188c2ecf20Sopenharmony_ci	*txdlh = NULL;
16198c2ecf20Sopenharmony_ci	status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
16208c2ecf20Sopenharmony_ciexit:
16218c2ecf20Sopenharmony_ci	return status;
16228c2ecf20Sopenharmony_ci}
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci/**
16258c2ecf20Sopenharmony_ci * vxge_hw_fifo_handle_tcode - Handle transfer code.
16268c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
16278c2ecf20Sopenharmony_ci * @txdlh: Descriptor handle.
16288c2ecf20Sopenharmony_ci * @t_code: One of the enumerated (and documented in the Titan user guide)
16298c2ecf20Sopenharmony_ci *          "transfer codes".
16308c2ecf20Sopenharmony_ci *
16318c2ecf20Sopenharmony_ci * Handle descriptor's transfer code. The latter comes with each completed
16328c2ecf20Sopenharmony_ci * descriptor.
16338c2ecf20Sopenharmony_ci *
16348c2ecf20Sopenharmony_ci * Returns: one of the enum vxge_hw_status{} enumerated types.
16358c2ecf20Sopenharmony_ci * VXGE_HW_OK - for success.
16368c2ecf20Sopenharmony_ci * VXGE_HW_ERR_CRITICAL - when encounters critical error.
16378c2ecf20Sopenharmony_ci */
16388c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_fifo_handle_tcode(struct __vxge_hw_fifo *fifo,
16398c2ecf20Sopenharmony_ci					      void *txdlh,
16408c2ecf20Sopenharmony_ci					      enum vxge_hw_fifo_tcode t_code)
16418c2ecf20Sopenharmony_ci{
16428c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	if (((t_code & 0x7) < 0) || ((t_code & 0x7) > 0x4)) {
16458c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_TCODE;
16468c2ecf20Sopenharmony_ci		goto exit;
16478c2ecf20Sopenharmony_ci	}
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	fifo->stats->txd_t_code_err_cnt[t_code]++;
16508c2ecf20Sopenharmony_ciexit:
16518c2ecf20Sopenharmony_ci	return status;
16528c2ecf20Sopenharmony_ci}
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci/**
16558c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_free - Free descriptor.
16568c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
16578c2ecf20Sopenharmony_ci * @txdlh: Descriptor handle.
16588c2ecf20Sopenharmony_ci *
16598c2ecf20Sopenharmony_ci * Free the reserved descriptor. This operation is "symmetrical" to
16608c2ecf20Sopenharmony_ci * vxge_hw_fifo_txdl_reserve. The "free-ing" completes the descriptor's
16618c2ecf20Sopenharmony_ci * lifecycle.
16628c2ecf20Sopenharmony_ci *
16638c2ecf20Sopenharmony_ci * After free-ing (see vxge_hw_fifo_txdl_free()) the descriptor again can
16648c2ecf20Sopenharmony_ci * be:
16658c2ecf20Sopenharmony_ci *
16668c2ecf20Sopenharmony_ci * - reserved (vxge_hw_fifo_txdl_reserve);
16678c2ecf20Sopenharmony_ci *
16688c2ecf20Sopenharmony_ci * - posted (vxge_hw_fifo_txdl_post);
16698c2ecf20Sopenharmony_ci *
16708c2ecf20Sopenharmony_ci * - completed (vxge_hw_fifo_txdl_next_completed);
16718c2ecf20Sopenharmony_ci *
16728c2ecf20Sopenharmony_ci * - and recycled again (vxge_hw_fifo_txdl_free).
16738c2ecf20Sopenharmony_ci *
16748c2ecf20Sopenharmony_ci * For alternative state transitions and more details please refer to
16758c2ecf20Sopenharmony_ci * the design doc.
16768c2ecf20Sopenharmony_ci *
16778c2ecf20Sopenharmony_ci */
16788c2ecf20Sopenharmony_civoid vxge_hw_fifo_txdl_free(struct __vxge_hw_fifo *fifo, void *txdlh)
16798c2ecf20Sopenharmony_ci{
16808c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	channel = &fifo->channel;
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	vxge_hw_channel_dtr_free(channel, txdlh);
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci/**
16888c2ecf20Sopenharmony_ci * vxge_hw_vpath_mac_addr_add - Add the mac address entry for this vpath to MAC address table.
16898c2ecf20Sopenharmony_ci * @vp: Vpath handle.
16908c2ecf20Sopenharmony_ci * @macaddr: MAC address to be added for this vpath into the list
16918c2ecf20Sopenharmony_ci * @macaddr_mask: MAC address mask for macaddr
16928c2ecf20Sopenharmony_ci * @duplicate_mode: Duplicate MAC address add mode. Please see
16938c2ecf20Sopenharmony_ci *             enum vxge_hw_vpath_mac_addr_add_mode{}
16948c2ecf20Sopenharmony_ci *
16958c2ecf20Sopenharmony_ci * Adds the given mac address and mac address mask into the list for this
16968c2ecf20Sopenharmony_ci * vpath.
16978c2ecf20Sopenharmony_ci * see also: vxge_hw_vpath_mac_addr_delete, vxge_hw_vpath_mac_addr_get and
16988c2ecf20Sopenharmony_ci * vxge_hw_vpath_mac_addr_get_next
16998c2ecf20Sopenharmony_ci *
17008c2ecf20Sopenharmony_ci */
17018c2ecf20Sopenharmony_cienum vxge_hw_status
17028c2ecf20Sopenharmony_civxge_hw_vpath_mac_addr_add(
17038c2ecf20Sopenharmony_ci	struct __vxge_hw_vpath_handle *vp,
17048c2ecf20Sopenharmony_ci	u8 *macaddr,
17058c2ecf20Sopenharmony_ci	u8 *macaddr_mask,
17068c2ecf20Sopenharmony_ci	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode)
17078c2ecf20Sopenharmony_ci{
17088c2ecf20Sopenharmony_ci	u32 i;
17098c2ecf20Sopenharmony_ci	u64 data1 = 0ULL;
17108c2ecf20Sopenharmony_ci	u64 data2 = 0ULL;
17118c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci	if (vp == NULL) {
17148c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
17158c2ecf20Sopenharmony_ci		goto exit;
17168c2ecf20Sopenharmony_ci	}
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	for (i = 0; i < ETH_ALEN; i++) {
17198c2ecf20Sopenharmony_ci		data1 <<= 8;
17208c2ecf20Sopenharmony_ci		data1 |= (u8)macaddr[i];
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci		data2 <<= 8;
17238c2ecf20Sopenharmony_ci		data2 |= (u8)macaddr_mask[i];
17248c2ecf20Sopenharmony_ci	}
17258c2ecf20Sopenharmony_ci
17268c2ecf20Sopenharmony_ci	switch (duplicate_mode) {
17278c2ecf20Sopenharmony_ci	case VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE:
17288c2ecf20Sopenharmony_ci		i = 0;
17298c2ecf20Sopenharmony_ci		break;
17308c2ecf20Sopenharmony_ci	case VXGE_HW_VPATH_MAC_ADDR_DISCARD_DUPLICATE:
17318c2ecf20Sopenharmony_ci		i = 1;
17328c2ecf20Sopenharmony_ci		break;
17338c2ecf20Sopenharmony_ci	case VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE:
17348c2ecf20Sopenharmony_ci		i = 2;
17358c2ecf20Sopenharmony_ci		break;
17368c2ecf20Sopenharmony_ci	default:
17378c2ecf20Sopenharmony_ci		i = 0;
17388c2ecf20Sopenharmony_ci		break;
17398c2ecf20Sopenharmony_ci	}
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_set(vp,
17428c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY,
17438c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
17448c2ecf20Sopenharmony_ci			0,
17458c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR(data1),
17468c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK(data2)|
17478c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MODE(i));
17488c2ecf20Sopenharmony_ciexit:
17498c2ecf20Sopenharmony_ci	return status;
17508c2ecf20Sopenharmony_ci}
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci/**
17538c2ecf20Sopenharmony_ci * vxge_hw_vpath_mac_addr_get - Get the first mac address entry
17548c2ecf20Sopenharmony_ci * @vp: Vpath handle.
17558c2ecf20Sopenharmony_ci * @macaddr: First MAC address entry for this vpath in the list
17568c2ecf20Sopenharmony_ci * @macaddr_mask: MAC address mask for macaddr
17578c2ecf20Sopenharmony_ci *
17588c2ecf20Sopenharmony_ci * Get the first mac address entry for this vpath from MAC address table.
17598c2ecf20Sopenharmony_ci * Return: the first mac address and mac address mask in the list for this
17608c2ecf20Sopenharmony_ci * vpath.
17618c2ecf20Sopenharmony_ci * see also: vxge_hw_vpath_mac_addr_get_next
17628c2ecf20Sopenharmony_ci *
17638c2ecf20Sopenharmony_ci */
17648c2ecf20Sopenharmony_cienum vxge_hw_status
17658c2ecf20Sopenharmony_civxge_hw_vpath_mac_addr_get(
17668c2ecf20Sopenharmony_ci	struct __vxge_hw_vpath_handle *vp,
17678c2ecf20Sopenharmony_ci	u8 *macaddr,
17688c2ecf20Sopenharmony_ci	u8 *macaddr_mask)
17698c2ecf20Sopenharmony_ci{
17708c2ecf20Sopenharmony_ci	u32 i;
17718c2ecf20Sopenharmony_ci	u64 data1 = 0ULL;
17728c2ecf20Sopenharmony_ci	u64 data2 = 0ULL;
17738c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	if (vp == NULL) {
17768c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
17778c2ecf20Sopenharmony_ci		goto exit;
17788c2ecf20Sopenharmony_ci	}
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_get(vp,
17818c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY,
17828c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
17838c2ecf20Sopenharmony_ci			0, &data1, &data2);
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
17868c2ecf20Sopenharmony_ci		goto exit;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	data1 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1);
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	data2 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(data2);
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ci	for (i = ETH_ALEN; i > 0; i--) {
17938c2ecf20Sopenharmony_ci		macaddr[i-1] = (u8)(data1 & 0xFF);
17948c2ecf20Sopenharmony_ci		data1 >>= 8;
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci		macaddr_mask[i-1] = (u8)(data2 & 0xFF);
17978c2ecf20Sopenharmony_ci		data2 >>= 8;
17988c2ecf20Sopenharmony_ci	}
17998c2ecf20Sopenharmony_ciexit:
18008c2ecf20Sopenharmony_ci	return status;
18018c2ecf20Sopenharmony_ci}
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_ci/**
18048c2ecf20Sopenharmony_ci * vxge_hw_vpath_mac_addr_get_next - Get the next mac address entry
18058c2ecf20Sopenharmony_ci * @vp: Vpath handle.
18068c2ecf20Sopenharmony_ci * @macaddr: Next MAC address entry for this vpath in the list
18078c2ecf20Sopenharmony_ci * @macaddr_mask: MAC address mask for macaddr
18088c2ecf20Sopenharmony_ci *
18098c2ecf20Sopenharmony_ci * Get the next mac address entry for this vpath from MAC address table.
18108c2ecf20Sopenharmony_ci * Return: the next mac address and mac address mask in the list for this
18118c2ecf20Sopenharmony_ci * vpath.
18128c2ecf20Sopenharmony_ci * see also: vxge_hw_vpath_mac_addr_get
18138c2ecf20Sopenharmony_ci *
18148c2ecf20Sopenharmony_ci */
18158c2ecf20Sopenharmony_cienum vxge_hw_status
18168c2ecf20Sopenharmony_civxge_hw_vpath_mac_addr_get_next(
18178c2ecf20Sopenharmony_ci	struct __vxge_hw_vpath_handle *vp,
18188c2ecf20Sopenharmony_ci	u8 *macaddr,
18198c2ecf20Sopenharmony_ci	u8 *macaddr_mask)
18208c2ecf20Sopenharmony_ci{
18218c2ecf20Sopenharmony_ci	u32 i;
18228c2ecf20Sopenharmony_ci	u64 data1 = 0ULL;
18238c2ecf20Sopenharmony_ci	u64 data2 = 0ULL;
18248c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	if (vp == NULL) {
18278c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
18288c2ecf20Sopenharmony_ci		goto exit;
18298c2ecf20Sopenharmony_ci	}
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_get(vp,
18328c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY,
18338c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
18348c2ecf20Sopenharmony_ci			0, &data1, &data2);
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
18378c2ecf20Sopenharmony_ci		goto exit;
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci	data1 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1);
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci	data2 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(data2);
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	for (i = ETH_ALEN; i > 0; i--) {
18448c2ecf20Sopenharmony_ci		macaddr[i-1] = (u8)(data1 & 0xFF);
18458c2ecf20Sopenharmony_ci		data1 >>= 8;
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci		macaddr_mask[i-1] = (u8)(data2 & 0xFF);
18488c2ecf20Sopenharmony_ci		data2 >>= 8;
18498c2ecf20Sopenharmony_ci	}
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ciexit:
18528c2ecf20Sopenharmony_ci	return status;
18538c2ecf20Sopenharmony_ci}
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci/**
18568c2ecf20Sopenharmony_ci * vxge_hw_vpath_mac_addr_delete - Delete the mac address entry for this vpath to MAC address table.
18578c2ecf20Sopenharmony_ci * @vp: Vpath handle.
18588c2ecf20Sopenharmony_ci * @macaddr: MAC address to be added for this vpath into the list
18598c2ecf20Sopenharmony_ci * @macaddr_mask: MAC address mask for macaddr
18608c2ecf20Sopenharmony_ci *
18618c2ecf20Sopenharmony_ci * Delete the given mac address and mac address mask into the list for this
18628c2ecf20Sopenharmony_ci * vpath.
18638c2ecf20Sopenharmony_ci * see also: vxge_hw_vpath_mac_addr_add, vxge_hw_vpath_mac_addr_get and
18648c2ecf20Sopenharmony_ci * vxge_hw_vpath_mac_addr_get_next
18658c2ecf20Sopenharmony_ci *
18668c2ecf20Sopenharmony_ci */
18678c2ecf20Sopenharmony_cienum vxge_hw_status
18688c2ecf20Sopenharmony_civxge_hw_vpath_mac_addr_delete(
18698c2ecf20Sopenharmony_ci	struct __vxge_hw_vpath_handle *vp,
18708c2ecf20Sopenharmony_ci	u8 *macaddr,
18718c2ecf20Sopenharmony_ci	u8 *macaddr_mask)
18728c2ecf20Sopenharmony_ci{
18738c2ecf20Sopenharmony_ci	u32 i;
18748c2ecf20Sopenharmony_ci	u64 data1 = 0ULL;
18758c2ecf20Sopenharmony_ci	u64 data2 = 0ULL;
18768c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_ci	if (vp == NULL) {
18798c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
18808c2ecf20Sopenharmony_ci		goto exit;
18818c2ecf20Sopenharmony_ci	}
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	for (i = 0; i < ETH_ALEN; i++) {
18848c2ecf20Sopenharmony_ci		data1 <<= 8;
18858c2ecf20Sopenharmony_ci		data1 |= (u8)macaddr[i];
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci		data2 <<= 8;
18888c2ecf20Sopenharmony_ci		data2 |= (u8)macaddr_mask[i];
18898c2ecf20Sopenharmony_ci	}
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_set(vp,
18928c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY,
18938c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
18948c2ecf20Sopenharmony_ci			0,
18958c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR(data1),
18968c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK(data2));
18978c2ecf20Sopenharmony_ciexit:
18988c2ecf20Sopenharmony_ci	return status;
18998c2ecf20Sopenharmony_ci}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci/**
19028c2ecf20Sopenharmony_ci * vxge_hw_vpath_vid_add - Add the vlan id entry for this vpath to vlan id table.
19038c2ecf20Sopenharmony_ci * @vp: Vpath handle.
19048c2ecf20Sopenharmony_ci * @vid: vlan id to be added for this vpath into the list
19058c2ecf20Sopenharmony_ci *
19068c2ecf20Sopenharmony_ci * Adds the given vlan id into the list for this  vpath.
19078c2ecf20Sopenharmony_ci * see also: vxge_hw_vpath_vid_delete
19088c2ecf20Sopenharmony_ci *
19098c2ecf20Sopenharmony_ci */
19108c2ecf20Sopenharmony_cienum vxge_hw_status
19118c2ecf20Sopenharmony_civxge_hw_vpath_vid_add(struct __vxge_hw_vpath_handle *vp, u64 vid)
19128c2ecf20Sopenharmony_ci{
19138c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	if (vp == NULL) {
19168c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
19178c2ecf20Sopenharmony_ci		goto exit;
19188c2ecf20Sopenharmony_ci	}
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_set(vp,
19218c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY,
19228c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID,
19238c2ecf20Sopenharmony_ci			0, VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID(vid), 0);
19248c2ecf20Sopenharmony_ciexit:
19258c2ecf20Sopenharmony_ci	return status;
19268c2ecf20Sopenharmony_ci}
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci/**
19298c2ecf20Sopenharmony_ci * vxge_hw_vpath_vid_delete - Delete the vlan id entry for this vpath
19308c2ecf20Sopenharmony_ci *               to vlan id table.
19318c2ecf20Sopenharmony_ci * @vp: Vpath handle.
19328c2ecf20Sopenharmony_ci * @vid: vlan id to be added for this vpath into the list
19338c2ecf20Sopenharmony_ci *
19348c2ecf20Sopenharmony_ci * Adds the given vlan id into the list for this  vpath.
19358c2ecf20Sopenharmony_ci * see also: vxge_hw_vpath_vid_add
19368c2ecf20Sopenharmony_ci *
19378c2ecf20Sopenharmony_ci */
19388c2ecf20Sopenharmony_cienum vxge_hw_status
19398c2ecf20Sopenharmony_civxge_hw_vpath_vid_delete(struct __vxge_hw_vpath_handle *vp, u64 vid)
19408c2ecf20Sopenharmony_ci{
19418c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	if (vp == NULL) {
19448c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
19458c2ecf20Sopenharmony_ci		goto exit;
19468c2ecf20Sopenharmony_ci	}
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_set(vp,
19498c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY,
19508c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID,
19518c2ecf20Sopenharmony_ci			0, VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID(vid), 0);
19528c2ecf20Sopenharmony_ciexit:
19538c2ecf20Sopenharmony_ci	return status;
19548c2ecf20Sopenharmony_ci}
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci/**
19578c2ecf20Sopenharmony_ci * vxge_hw_vpath_promisc_enable - Enable promiscuous mode.
19588c2ecf20Sopenharmony_ci * @vp: Vpath handle.
19598c2ecf20Sopenharmony_ci *
19608c2ecf20Sopenharmony_ci * Enable promiscuous mode of Titan-e operation.
19618c2ecf20Sopenharmony_ci *
19628c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_promisc_disable().
19638c2ecf20Sopenharmony_ci */
19648c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_promisc_enable(
19658c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp)
19668c2ecf20Sopenharmony_ci{
19678c2ecf20Sopenharmony_ci	u64 val64;
19688c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
19698c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
19728c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
19738c2ecf20Sopenharmony_ci		goto exit;
19748c2ecf20Sopenharmony_ci	}
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	vpath = vp->vpath;
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci	/* Enable promiscuous mode for function 0 only */
19798c2ecf20Sopenharmony_ci	if (!(vpath->hldev->access_rights &
19808c2ecf20Sopenharmony_ci		VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM))
19818c2ecf20Sopenharmony_ci		return VXGE_HW_OK;
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	if (!(val64 & VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN)) {
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN |
19888c2ecf20Sopenharmony_ci			 VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN |
19898c2ecf20Sopenharmony_ci			 VXGE_HW_RXMAC_VCFG0_BCAST_EN |
19908c2ecf20Sopenharmony_ci			 VXGE_HW_RXMAC_VCFG0_ALL_VID_EN;
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
19938c2ecf20Sopenharmony_ci	}
19948c2ecf20Sopenharmony_ciexit:
19958c2ecf20Sopenharmony_ci	return status;
19968c2ecf20Sopenharmony_ci}
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci/**
19998c2ecf20Sopenharmony_ci * vxge_hw_vpath_promisc_disable - Disable promiscuous mode.
20008c2ecf20Sopenharmony_ci * @vp: Vpath handle.
20018c2ecf20Sopenharmony_ci *
20028c2ecf20Sopenharmony_ci * Disable promiscuous mode of Titan-e operation.
20038c2ecf20Sopenharmony_ci *
20048c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_promisc_enable().
20058c2ecf20Sopenharmony_ci */
20068c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_promisc_disable(
20078c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp)
20088c2ecf20Sopenharmony_ci{
20098c2ecf20Sopenharmony_ci	u64 val64;
20108c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
20118c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
20128c2ecf20Sopenharmony_ci
20138c2ecf20Sopenharmony_ci	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
20148c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
20158c2ecf20Sopenharmony_ci		goto exit;
20168c2ecf20Sopenharmony_ci	}
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci	vpath = vp->vpath;
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN) {
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci		val64 &= ~(VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN |
20258c2ecf20Sopenharmony_ci			   VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN |
20268c2ecf20Sopenharmony_ci			   VXGE_HW_RXMAC_VCFG0_ALL_VID_EN);
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
20298c2ecf20Sopenharmony_ci	}
20308c2ecf20Sopenharmony_ciexit:
20318c2ecf20Sopenharmony_ci	return status;
20328c2ecf20Sopenharmony_ci}
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci/*
20358c2ecf20Sopenharmony_ci * vxge_hw_vpath_bcast_enable - Enable broadcast
20368c2ecf20Sopenharmony_ci * @vp: Vpath handle.
20378c2ecf20Sopenharmony_ci *
20388c2ecf20Sopenharmony_ci * Enable receiving broadcasts.
20398c2ecf20Sopenharmony_ci */
20408c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_bcast_enable(
20418c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp)
20428c2ecf20Sopenharmony_ci{
20438c2ecf20Sopenharmony_ci	u64 val64;
20448c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
20458c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
20488c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
20498c2ecf20Sopenharmony_ci		goto exit;
20508c2ecf20Sopenharmony_ci	}
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	vpath = vp->vpath;
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	if (!(val64 & VXGE_HW_RXMAC_VCFG0_BCAST_EN)) {
20578c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_RXMAC_VCFG0_BCAST_EN;
20588c2ecf20Sopenharmony_ci		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
20598c2ecf20Sopenharmony_ci	}
20608c2ecf20Sopenharmony_ciexit:
20618c2ecf20Sopenharmony_ci	return status;
20628c2ecf20Sopenharmony_ci}
20638c2ecf20Sopenharmony_ci
20648c2ecf20Sopenharmony_ci/**
20658c2ecf20Sopenharmony_ci * vxge_hw_vpath_mcast_enable - Enable multicast addresses.
20668c2ecf20Sopenharmony_ci * @vp: Vpath handle.
20678c2ecf20Sopenharmony_ci *
20688c2ecf20Sopenharmony_ci * Enable Titan-e multicast addresses.
20698c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK on success.
20708c2ecf20Sopenharmony_ci *
20718c2ecf20Sopenharmony_ci */
20728c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_mcast_enable(
20738c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp)
20748c2ecf20Sopenharmony_ci{
20758c2ecf20Sopenharmony_ci	u64 val64;
20768c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
20778c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
20808c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
20818c2ecf20Sopenharmony_ci		goto exit;
20828c2ecf20Sopenharmony_ci	}
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	vpath = vp->vpath;
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci	if (!(val64 & VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN)) {
20898c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN;
20908c2ecf20Sopenharmony_ci		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
20918c2ecf20Sopenharmony_ci	}
20928c2ecf20Sopenharmony_ciexit:
20938c2ecf20Sopenharmony_ci	return status;
20948c2ecf20Sopenharmony_ci}
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci/**
20978c2ecf20Sopenharmony_ci * vxge_hw_vpath_mcast_disable - Disable  multicast addresses.
20988c2ecf20Sopenharmony_ci * @vp: Vpath handle.
20998c2ecf20Sopenharmony_ci *
21008c2ecf20Sopenharmony_ci * Disable Titan-e multicast addresses.
21018c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK - success.
21028c2ecf20Sopenharmony_ci * VXGE_HW_ERR_INVALID_HANDLE - Invalid handle
21038c2ecf20Sopenharmony_ci *
21048c2ecf20Sopenharmony_ci */
21058c2ecf20Sopenharmony_cienum vxge_hw_status
21068c2ecf20Sopenharmony_civxge_hw_vpath_mcast_disable(struct __vxge_hw_vpath_handle *vp)
21078c2ecf20Sopenharmony_ci{
21088c2ecf20Sopenharmony_ci	u64 val64;
21098c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
21108c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
21138c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
21148c2ecf20Sopenharmony_ci		goto exit;
21158c2ecf20Sopenharmony_ci	}
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci	vpath = vp->vpath;
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN) {
21228c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN;
21238c2ecf20Sopenharmony_ci		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
21248c2ecf20Sopenharmony_ci	}
21258c2ecf20Sopenharmony_ciexit:
21268c2ecf20Sopenharmony_ci	return status;
21278c2ecf20Sopenharmony_ci}
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci/*
21308c2ecf20Sopenharmony_ci * vxge_hw_vpath_alarm_process - Process Alarms.
21318c2ecf20Sopenharmony_ci * @vpath: Virtual Path.
21328c2ecf20Sopenharmony_ci * @skip_alarms: Do not clear the alarms
21338c2ecf20Sopenharmony_ci *
21348c2ecf20Sopenharmony_ci * Process vpath alarms.
21358c2ecf20Sopenharmony_ci *
21368c2ecf20Sopenharmony_ci */
21378c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_alarm_process(
21388c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp,
21398c2ecf20Sopenharmony_ci			u32 skip_alarms)
21408c2ecf20Sopenharmony_ci{
21418c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	if (vp == NULL) {
21448c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
21458c2ecf20Sopenharmony_ci		goto exit;
21468c2ecf20Sopenharmony_ci	}
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_alarm_process(vp->vpath, skip_alarms);
21498c2ecf20Sopenharmony_ciexit:
21508c2ecf20Sopenharmony_ci	return status;
21518c2ecf20Sopenharmony_ci}
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ci/**
21548c2ecf20Sopenharmony_ci * vxge_hw_vpath_msix_set - Associate MSIX vectors with TIM interrupts and
21558c2ecf20Sopenharmony_ci *                            alrms
21568c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
21578c2ecf20Sopenharmony_ci * @tim_msix_id: MSIX vectors associated with VXGE_HW_MAX_INTR_PER_VP number of
21588c2ecf20Sopenharmony_ci *             interrupts(Can be repeated). If fifo or ring are not enabled
21598c2ecf20Sopenharmony_ci *             the MSIX vector for that should be set to 0
21608c2ecf20Sopenharmony_ci * @alarm_msix_id: MSIX vector for alarm.
21618c2ecf20Sopenharmony_ci *
21628c2ecf20Sopenharmony_ci * This API will associate a given MSIX vector numbers with the four TIM
21638c2ecf20Sopenharmony_ci * interrupts and alarm interrupt.
21648c2ecf20Sopenharmony_ci */
21658c2ecf20Sopenharmony_civoid
21668c2ecf20Sopenharmony_civxge_hw_vpath_msix_set(struct __vxge_hw_vpath_handle *vp, int *tim_msix_id,
21678c2ecf20Sopenharmony_ci		       int alarm_msix_id)
21688c2ecf20Sopenharmony_ci{
21698c2ecf20Sopenharmony_ci	u64 val64;
21708c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath = vp->vpath;
21718c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
21728c2ecf20Sopenharmony_ci	u32 vp_id = vp->vpath->vp_id;
21738c2ecf20Sopenharmony_ci
21748c2ecf20Sopenharmony_ci	val64 =  VXGE_HW_INTERRUPT_CFG0_GROUP0_MSIX_FOR_TXTI(
21758c2ecf20Sopenharmony_ci		  (vp_id * 4) + tim_msix_id[0]) |
21768c2ecf20Sopenharmony_ci		 VXGE_HW_INTERRUPT_CFG0_GROUP1_MSIX_FOR_TXTI(
21778c2ecf20Sopenharmony_ci		  (vp_id * 4) + tim_msix_id[1]);
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->interrupt_cfg0);
21808c2ecf20Sopenharmony_ci
21818c2ecf20Sopenharmony_ci	writeq(VXGE_HW_INTERRUPT_CFG2_ALARM_MAP_TO_MSG(
21828c2ecf20Sopenharmony_ci			(vpath->hldev->first_vp_id * 4) + alarm_msix_id),
21838c2ecf20Sopenharmony_ci			&vp_reg->interrupt_cfg2);
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ci	if (vpath->hldev->config.intr_mode ==
21868c2ecf20Sopenharmony_ci					VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
21878c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
21888c2ecf20Sopenharmony_ci				VXGE_HW_ONE_SHOT_VECT0_EN_ONE_SHOT_VECT0_EN,
21898c2ecf20Sopenharmony_ci				0, 32), &vp_reg->one_shot_vect0_en);
21908c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
21918c2ecf20Sopenharmony_ci				VXGE_HW_ONE_SHOT_VECT1_EN_ONE_SHOT_VECT1_EN,
21928c2ecf20Sopenharmony_ci				0, 32), &vp_reg->one_shot_vect1_en);
21938c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
21948c2ecf20Sopenharmony_ci				VXGE_HW_ONE_SHOT_VECT2_EN_ONE_SHOT_VECT2_EN,
21958c2ecf20Sopenharmony_ci				0, 32), &vp_reg->one_shot_vect2_en);
21968c2ecf20Sopenharmony_ci	}
21978c2ecf20Sopenharmony_ci}
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci/**
22008c2ecf20Sopenharmony_ci * vxge_hw_vpath_msix_mask - Mask MSIX Vector.
22018c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
22028c2ecf20Sopenharmony_ci * @msix_id:  MSIX ID
22038c2ecf20Sopenharmony_ci *
22048c2ecf20Sopenharmony_ci * The function masks the msix interrupt for the given msix_id
22058c2ecf20Sopenharmony_ci *
22068c2ecf20Sopenharmony_ci * Returns: 0,
22078c2ecf20Sopenharmony_ci * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
22088c2ecf20Sopenharmony_ci * status.
22098c2ecf20Sopenharmony_ci * See also:
22108c2ecf20Sopenharmony_ci */
22118c2ecf20Sopenharmony_civoid
22128c2ecf20Sopenharmony_civxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vp, int msix_id)
22138c2ecf20Sopenharmony_ci{
22148c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = vp->vpath->hldev;
22158c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
22168c2ecf20Sopenharmony_ci		(u32) vxge_bVALn(vxge_mBIT(msix_id  >> 2), 0, 32),
22178c2ecf20Sopenharmony_ci		&hldev->common_reg->set_msix_mask_vect[msix_id % 4]);
22188c2ecf20Sopenharmony_ci}
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci/**
22218c2ecf20Sopenharmony_ci * vxge_hw_vpath_msix_clear - Clear MSIX Vector.
22228c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
22238c2ecf20Sopenharmony_ci * @msix_id:  MSI ID
22248c2ecf20Sopenharmony_ci *
22258c2ecf20Sopenharmony_ci * The function clears the msix interrupt for the given msix_id
22268c2ecf20Sopenharmony_ci *
22278c2ecf20Sopenharmony_ci * Returns: 0,
22288c2ecf20Sopenharmony_ci * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
22298c2ecf20Sopenharmony_ci * status.
22308c2ecf20Sopenharmony_ci * See also:
22318c2ecf20Sopenharmony_ci */
22328c2ecf20Sopenharmony_civoid vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id)
22338c2ecf20Sopenharmony_ci{
22348c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = vp->vpath->hldev;
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci	if (hldev->config.intr_mode == VXGE_HW_INTR_MODE_MSIX_ONE_SHOT)
22378c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper(
22388c2ecf20Sopenharmony_ci			(u32) vxge_bVALn(vxge_mBIT((msix_id >> 2)), 0, 32),
22398c2ecf20Sopenharmony_ci			&hldev->common_reg->clr_msix_one_shot_vec[msix_id % 4]);
22408c2ecf20Sopenharmony_ci	else
22418c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper(
22428c2ecf20Sopenharmony_ci			(u32) vxge_bVALn(vxge_mBIT((msix_id >> 2)), 0, 32),
22438c2ecf20Sopenharmony_ci			&hldev->common_reg->clear_msix_mask_vect[msix_id % 4]);
22448c2ecf20Sopenharmony_ci}
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci/**
22478c2ecf20Sopenharmony_ci * vxge_hw_vpath_msix_unmask - Unmask the MSIX Vector.
22488c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
22498c2ecf20Sopenharmony_ci * @msix_id:  MSI ID
22508c2ecf20Sopenharmony_ci *
22518c2ecf20Sopenharmony_ci * The function unmasks the msix interrupt for the given msix_id
22528c2ecf20Sopenharmony_ci *
22538c2ecf20Sopenharmony_ci * Returns: 0,
22548c2ecf20Sopenharmony_ci * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
22558c2ecf20Sopenharmony_ci * status.
22568c2ecf20Sopenharmony_ci * See also:
22578c2ecf20Sopenharmony_ci */
22588c2ecf20Sopenharmony_civoid
22598c2ecf20Sopenharmony_civxge_hw_vpath_msix_unmask(struct __vxge_hw_vpath_handle *vp, int msix_id)
22608c2ecf20Sopenharmony_ci{
22618c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = vp->vpath->hldev;
22628c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper(
22638c2ecf20Sopenharmony_ci			(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
22648c2ecf20Sopenharmony_ci			&hldev->common_reg->clear_msix_mask_vect[msix_id%4]);
22658c2ecf20Sopenharmony_ci}
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci/**
22688c2ecf20Sopenharmony_ci * vxge_hw_vpath_inta_mask_tx_rx - Mask Tx and Rx interrupts.
22698c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
22708c2ecf20Sopenharmony_ci *
22718c2ecf20Sopenharmony_ci * Mask Tx and Rx vpath interrupts.
22728c2ecf20Sopenharmony_ci *
22738c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_inta_mask_tx_rx()
22748c2ecf20Sopenharmony_ci */
22758c2ecf20Sopenharmony_civoid vxge_hw_vpath_inta_mask_tx_rx(struct __vxge_hw_vpath_handle *vp)
22768c2ecf20Sopenharmony_ci{
22778c2ecf20Sopenharmony_ci	u64	tim_int_mask0[4] = {[0 ...3] = 0};
22788c2ecf20Sopenharmony_ci	u32	tim_int_mask1[4] = {[0 ...3] = 0};
22798c2ecf20Sopenharmony_ci	u64	val64;
22808c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = vp->vpath->hldev;
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci	VXGE_HW_DEVICE_TIM_INT_MASK_SET(tim_int_mask0,
22838c2ecf20Sopenharmony_ci		tim_int_mask1, vp->vpath->vp_id);
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci	val64 = readq(&hldev->common_reg->tim_int_mask0);
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci	if ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
22888c2ecf20Sopenharmony_ci		(tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
22898c2ecf20Sopenharmony_ci		writeq((tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
22908c2ecf20Sopenharmony_ci			tim_int_mask0[VXGE_HW_VPATH_INTR_RX] | val64),
22918c2ecf20Sopenharmony_ci			&hldev->common_reg->tim_int_mask0);
22928c2ecf20Sopenharmony_ci	}
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_ci	val64 = readl(&hldev->common_reg->tim_int_mask1);
22958c2ecf20Sopenharmony_ci
22968c2ecf20Sopenharmony_ci	if ((tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
22978c2ecf20Sopenharmony_ci		(tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
22988c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper(
22998c2ecf20Sopenharmony_ci			(tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
23008c2ecf20Sopenharmony_ci			tim_int_mask1[VXGE_HW_VPATH_INTR_RX] | val64),
23018c2ecf20Sopenharmony_ci			&hldev->common_reg->tim_int_mask1);
23028c2ecf20Sopenharmony_ci	}
23038c2ecf20Sopenharmony_ci}
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci/**
23068c2ecf20Sopenharmony_ci * vxge_hw_vpath_inta_unmask_tx_rx - Unmask Tx and Rx interrupts.
23078c2ecf20Sopenharmony_ci * @vp: Virtual Path handle.
23088c2ecf20Sopenharmony_ci *
23098c2ecf20Sopenharmony_ci * Unmask Tx and Rx vpath interrupts.
23108c2ecf20Sopenharmony_ci *
23118c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_inta_mask_tx_rx()
23128c2ecf20Sopenharmony_ci */
23138c2ecf20Sopenharmony_civoid vxge_hw_vpath_inta_unmask_tx_rx(struct __vxge_hw_vpath_handle *vp)
23148c2ecf20Sopenharmony_ci{
23158c2ecf20Sopenharmony_ci	u64	tim_int_mask0[4] = {[0 ...3] = 0};
23168c2ecf20Sopenharmony_ci	u32	tim_int_mask1[4] = {[0 ...3] = 0};
23178c2ecf20Sopenharmony_ci	u64	val64;
23188c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = vp->vpath->hldev;
23198c2ecf20Sopenharmony_ci
23208c2ecf20Sopenharmony_ci	VXGE_HW_DEVICE_TIM_INT_MASK_SET(tim_int_mask0,
23218c2ecf20Sopenharmony_ci		tim_int_mask1, vp->vpath->vp_id);
23228c2ecf20Sopenharmony_ci
23238c2ecf20Sopenharmony_ci	val64 = readq(&hldev->common_reg->tim_int_mask0);
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_ci	if ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
23268c2ecf20Sopenharmony_ci	   (tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
23278c2ecf20Sopenharmony_ci		writeq((~(tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
23288c2ecf20Sopenharmony_ci			tim_int_mask0[VXGE_HW_VPATH_INTR_RX])) & val64,
23298c2ecf20Sopenharmony_ci			&hldev->common_reg->tim_int_mask0);
23308c2ecf20Sopenharmony_ci	}
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	if ((tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
23338c2ecf20Sopenharmony_ci	   (tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
23348c2ecf20Sopenharmony_ci		__vxge_hw_pio_mem_write32_upper(
23358c2ecf20Sopenharmony_ci			(~(tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
23368c2ecf20Sopenharmony_ci			  tim_int_mask1[VXGE_HW_VPATH_INTR_RX])) & val64,
23378c2ecf20Sopenharmony_ci			&hldev->common_reg->tim_int_mask1);
23388c2ecf20Sopenharmony_ci	}
23398c2ecf20Sopenharmony_ci}
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ci/**
23428c2ecf20Sopenharmony_ci * vxge_hw_vpath_poll_rx - Poll Rx Virtual Path for completed
23438c2ecf20Sopenharmony_ci * descriptors and process the same.
23448c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
23458c2ecf20Sopenharmony_ci *
23468c2ecf20Sopenharmony_ci * The function	polls the Rx for the completed	descriptors and	calls
23478c2ecf20Sopenharmony_ci * the driver via supplied completion	callback.
23488c2ecf20Sopenharmony_ci *
23498c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK, if the polling is completed successful.
23508c2ecf20Sopenharmony_ci * VXGE_HW_COMPLETIONS_REMAIN: There are still more completed
23518c2ecf20Sopenharmony_ci * descriptors available which are yet to be processed.
23528c2ecf20Sopenharmony_ci *
23538c2ecf20Sopenharmony_ci * See also: vxge_hw_vpath_poll_rx()
23548c2ecf20Sopenharmony_ci */
23558c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_poll_rx(struct __vxge_hw_ring *ring)
23568c2ecf20Sopenharmony_ci{
23578c2ecf20Sopenharmony_ci	u8 t_code;
23588c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
23598c2ecf20Sopenharmony_ci	void *first_rxdh;
23608c2ecf20Sopenharmony_ci	int new_count = 0;
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_ci	ring->cmpl_cnt = 0;
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci	status = vxge_hw_ring_rxd_next_completed(ring, &first_rxdh, &t_code);
23658c2ecf20Sopenharmony_ci	if (status == VXGE_HW_OK)
23668c2ecf20Sopenharmony_ci		ring->callback(ring, first_rxdh,
23678c2ecf20Sopenharmony_ci			t_code, ring->channel.userdata);
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci	if (ring->cmpl_cnt != 0) {
23708c2ecf20Sopenharmony_ci		ring->doorbell_cnt += ring->cmpl_cnt;
23718c2ecf20Sopenharmony_ci		if (ring->doorbell_cnt >= ring->rxds_limit) {
23728c2ecf20Sopenharmony_ci			/*
23738c2ecf20Sopenharmony_ci			 * Each RxD is of 4 qwords, update the number of
23748c2ecf20Sopenharmony_ci			 * qwords replenished
23758c2ecf20Sopenharmony_ci			 */
23768c2ecf20Sopenharmony_ci			new_count = (ring->doorbell_cnt * 4);
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_ci			/* For each block add 4 more qwords */
23798c2ecf20Sopenharmony_ci			ring->total_db_cnt += ring->doorbell_cnt;
23808c2ecf20Sopenharmony_ci			if (ring->total_db_cnt >= ring->rxds_per_block) {
23818c2ecf20Sopenharmony_ci				new_count += 4;
23828c2ecf20Sopenharmony_ci				/* Reset total count */
23838c2ecf20Sopenharmony_ci				ring->total_db_cnt %= ring->rxds_per_block;
23848c2ecf20Sopenharmony_ci			}
23858c2ecf20Sopenharmony_ci			writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(new_count),
23868c2ecf20Sopenharmony_ci				&ring->vp_reg->prc_rxd_doorbell);
23878c2ecf20Sopenharmony_ci			readl(&ring->common_reg->titan_general_int_status);
23888c2ecf20Sopenharmony_ci			ring->doorbell_cnt = 0;
23898c2ecf20Sopenharmony_ci		}
23908c2ecf20Sopenharmony_ci	}
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci	return status;
23938c2ecf20Sopenharmony_ci}
23948c2ecf20Sopenharmony_ci
23958c2ecf20Sopenharmony_ci/**
23968c2ecf20Sopenharmony_ci * vxge_hw_vpath_poll_tx - Poll Tx for completed descriptors and process the same.
23978c2ecf20Sopenharmony_ci * @fifo: Handle to the fifo object used for non offload send
23988c2ecf20Sopenharmony_ci * @skb_ptr: pointer to skb
23998c2ecf20Sopenharmony_ci * @nr_skb: number of skbs
24008c2ecf20Sopenharmony_ci * @more: more is coming
24018c2ecf20Sopenharmony_ci *
24028c2ecf20Sopenharmony_ci * The function polls the Tx for the completed descriptors and calls
24038c2ecf20Sopenharmony_ci * the driver via supplied completion callback.
24048c2ecf20Sopenharmony_ci *
24058c2ecf20Sopenharmony_ci * Returns: VXGE_HW_OK, if the polling is completed successful.
24068c2ecf20Sopenharmony_ci * VXGE_HW_COMPLETIONS_REMAIN: There are still more completed
24078c2ecf20Sopenharmony_ci * descriptors available which are yet to be processed.
24088c2ecf20Sopenharmony_ci */
24098c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo,
24108c2ecf20Sopenharmony_ci					struct sk_buff ***skb_ptr, int nr_skb,
24118c2ecf20Sopenharmony_ci					int *more)
24128c2ecf20Sopenharmony_ci{
24138c2ecf20Sopenharmony_ci	enum vxge_hw_fifo_tcode t_code;
24148c2ecf20Sopenharmony_ci	void *first_txdlh;
24158c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
24168c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci	channel = &fifo->channel;
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci	status = vxge_hw_fifo_txdl_next_completed(fifo,
24218c2ecf20Sopenharmony_ci				&first_txdlh, &t_code);
24228c2ecf20Sopenharmony_ci	if (status == VXGE_HW_OK)
24238c2ecf20Sopenharmony_ci		if (fifo->callback(fifo, first_txdlh, t_code,
24248c2ecf20Sopenharmony_ci			channel->userdata, skb_ptr, nr_skb, more) != VXGE_HW_OK)
24258c2ecf20Sopenharmony_ci			status = VXGE_HW_COMPLETIONS_REMAIN;
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci	return status;
24288c2ecf20Sopenharmony_ci}
2429