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-config.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/vmalloc.h>
158c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
168c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h>
178c2ecf20Sopenharmony_ci#include <linux/pci.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "vxge-traffic.h"
218c2ecf20Sopenharmony_ci#include "vxge-config.h"
228c2ecf20Sopenharmony_ci#include "vxge-main.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define VXGE_HW_VPATH_STATS_PIO_READ(offset) {				\
258c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_stats_access(vpath,			\
268c2ecf20Sopenharmony_ci					      VXGE_HW_STATS_OP_READ,	\
278c2ecf20Sopenharmony_ci					      offset,			\
288c2ecf20Sopenharmony_ci					      &val64);			\
298c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)					\
308c2ecf20Sopenharmony_ci		return status;						\
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic void
348c2ecf20Sopenharmony_civxge_hw_vpath_set_zero_rx_frm_len(struct vxge_hw_vpath_reg __iomem *vp_reg)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	u64 val64;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rxmac_vcfg0);
398c2ecf20Sopenharmony_ci	val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
408c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->rxmac_vcfg0);
418c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rxmac_vcfg0);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * vxge_hw_vpath_wait_receive_idle - Wait for Rx to become idle
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_ciint vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
508c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
518c2ecf20Sopenharmony_ci	u64 val64, rxd_count, rxd_spat;
528c2ecf20Sopenharmony_ci	int count = 0, total_count = 0;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
558c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	vxge_hw_vpath_set_zero_rx_frm_len(vp_reg);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	/* Check that the ring controller for this vpath has enough free RxDs
608c2ecf20Sopenharmony_ci	 * to send frames to the host.  This is done by reading the
618c2ecf20Sopenharmony_ci	 * PRC_RXD_DOORBELL_VPn register and comparing the read value to the
628c2ecf20Sopenharmony_ci	 * RXD_SPAT value for the vpath.
638c2ecf20Sopenharmony_ci	 */
648c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->prc_cfg6);
658c2ecf20Sopenharmony_ci	rxd_spat = VXGE_HW_PRC_CFG6_GET_RXD_SPAT(val64) + 1;
668c2ecf20Sopenharmony_ci	/* Use a factor of 2 when comparing rxd_count against rxd_spat for some
678c2ecf20Sopenharmony_ci	 * leg room.
688c2ecf20Sopenharmony_ci	 */
698c2ecf20Sopenharmony_ci	rxd_spat *= 2;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	do {
728c2ecf20Sopenharmony_ci		mdelay(1);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci		rxd_count = readq(&vp_reg->prc_rxd_doorbell);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci		/* Check that the ring controller for this vpath does
778c2ecf20Sopenharmony_ci		 * not have any frame in its pipeline.
788c2ecf20Sopenharmony_ci		 */
798c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->frm_in_progress_cnt);
808c2ecf20Sopenharmony_ci		if ((rxd_count <= rxd_spat) || (val64 > 0))
818c2ecf20Sopenharmony_ci			count = 0;
828c2ecf20Sopenharmony_ci		else
838c2ecf20Sopenharmony_ci			count++;
848c2ecf20Sopenharmony_ci		total_count++;
858c2ecf20Sopenharmony_ci	} while ((count < VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT) &&
868c2ecf20Sopenharmony_ci			(total_count < VXGE_HW_MAX_POLLING_COUNT));
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
898c2ecf20Sopenharmony_ci		printk(KERN_ALERT "%s: Still Receiving traffic. Abort wait\n",
908c2ecf20Sopenharmony_ci			__func__);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	return total_count;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* vxge_hw_device_wait_receive_idle - This function waits until all frames
968c2ecf20Sopenharmony_ci * stored in the frame buffer for each vpath assigned to the given
978c2ecf20Sopenharmony_ci * function (hldev) have been sent to the host.
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_civoid vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	int i, total_count = 0;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
1048c2ecf20Sopenharmony_ci		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
1058c2ecf20Sopenharmony_ci			continue;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci		total_count += vxge_hw_vpath_wait_receive_idle(hldev, i);
1088c2ecf20Sopenharmony_ci		if (total_count >= VXGE_HW_MAX_POLLING_COUNT)
1098c2ecf20Sopenharmony_ci			break;
1108c2ecf20Sopenharmony_ci	}
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci/*
1148c2ecf20Sopenharmony_ci * __vxge_hw_device_register_poll
1158c2ecf20Sopenharmony_ci * Will poll certain register for specified amount of time.
1168c2ecf20Sopenharmony_ci * Will poll until masked bit is not cleared.
1178c2ecf20Sopenharmony_ci */
1188c2ecf20Sopenharmony_cistatic enum vxge_hw_status
1198c2ecf20Sopenharmony_ci__vxge_hw_device_register_poll(void __iomem *reg, u64 mask, u32 max_millis)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	u64 val64;
1228c2ecf20Sopenharmony_ci	u32 i = 0;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	udelay(10);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	do {
1278c2ecf20Sopenharmony_ci		val64 = readq(reg);
1288c2ecf20Sopenharmony_ci		if (!(val64 & mask))
1298c2ecf20Sopenharmony_ci			return VXGE_HW_OK;
1308c2ecf20Sopenharmony_ci		udelay(100);
1318c2ecf20Sopenharmony_ci	} while (++i <= 9);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	i = 0;
1348c2ecf20Sopenharmony_ci	do {
1358c2ecf20Sopenharmony_ci		val64 = readq(reg);
1368c2ecf20Sopenharmony_ci		if (!(val64 & mask))
1378c2ecf20Sopenharmony_ci			return VXGE_HW_OK;
1388c2ecf20Sopenharmony_ci		mdelay(1);
1398c2ecf20Sopenharmony_ci	} while (++i <= max_millis);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	return VXGE_HW_FAIL;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic inline enum vxge_hw_status
1458c2ecf20Sopenharmony_ci__vxge_hw_pio_mem_write64(u64 val64, void __iomem *addr,
1468c2ecf20Sopenharmony_ci			  u64 mask, u32 max_millis)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_lower((u32)vxge_bVALn(val64, 32, 32), addr);
1498c2ecf20Sopenharmony_ci	wmb();
1508c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32), addr);
1518c2ecf20Sopenharmony_ci	wmb();
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	return __vxge_hw_device_register_poll(addr, mask, max_millis);
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic enum vxge_hw_status
1578c2ecf20Sopenharmony_civxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action,
1588c2ecf20Sopenharmony_ci		     u32 fw_memo, u32 offset, u64 *data0, u64 *data1,
1598c2ecf20Sopenharmony_ci		     u64 *steer_ctrl)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
1628c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
1638c2ecf20Sopenharmony_ci	u64 val64;
1648c2ecf20Sopenharmony_ci	u32 retry = 0, max_retry = 3;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	spin_lock(&vpath->lock);
1678c2ecf20Sopenharmony_ci	if (!vpath->vp_open) {
1688c2ecf20Sopenharmony_ci		spin_unlock(&vpath->lock);
1698c2ecf20Sopenharmony_ci		max_retry = 100;
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	writeq(*data0, &vp_reg->rts_access_steer_data0);
1738c2ecf20Sopenharmony_ci	writeq(*data1, &vp_reg->rts_access_steer_data1);
1748c2ecf20Sopenharmony_ci	wmb();
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	val64 = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION(action) |
1778c2ecf20Sopenharmony_ci		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL(fw_memo) |
1788c2ecf20Sopenharmony_ci		VXGE_HW_RTS_ACCESS_STEER_CTRL_OFFSET(offset) |
1798c2ecf20Sopenharmony_ci		VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE |
1808c2ecf20Sopenharmony_ci		*steer_ctrl;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	status = __vxge_hw_pio_mem_write64(val64,
1838c2ecf20Sopenharmony_ci					   &vp_reg->rts_access_steer_ctrl,
1848c2ecf20Sopenharmony_ci					   VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
1858c2ecf20Sopenharmony_ci					   VXGE_HW_DEF_DEVICE_POLL_MILLIS);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	/* The __vxge_hw_device_register_poll can udelay for a significant
1888c2ecf20Sopenharmony_ci	 * amount of time, blocking other process from the CPU.  If it delays
1898c2ecf20Sopenharmony_ci	 * for ~5secs, a NMI error can occur.  A way around this is to give up
1908c2ecf20Sopenharmony_ci	 * the processor via msleep, but this is not allowed is under lock.
1918c2ecf20Sopenharmony_ci	 * So, only allow it to sleep for ~4secs if open.  Otherwise, delay for
1928c2ecf20Sopenharmony_ci	 * 1sec and sleep for 10ms until the firmware operation has completed
1938c2ecf20Sopenharmony_ci	 * or timed-out.
1948c2ecf20Sopenharmony_ci	 */
1958c2ecf20Sopenharmony_ci	while ((status != VXGE_HW_OK) && retry++ < max_retry) {
1968c2ecf20Sopenharmony_ci		if (!vpath->vp_open)
1978c2ecf20Sopenharmony_ci			msleep(20);
1988c2ecf20Sopenharmony_ci		status = __vxge_hw_device_register_poll(
1998c2ecf20Sopenharmony_ci					&vp_reg->rts_access_steer_ctrl,
2008c2ecf20Sopenharmony_ci					VXGE_HW_RTS_ACCESS_STEER_CTRL_STROBE,
2018c2ecf20Sopenharmony_ci					VXGE_HW_DEF_DEVICE_POLL_MILLIS);
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
2058c2ecf20Sopenharmony_ci		goto out;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rts_access_steer_ctrl);
2088c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_RTS_ACCESS_STEER_CTRL_RMACJ_STATUS) {
2098c2ecf20Sopenharmony_ci		*data0 = readq(&vp_reg->rts_access_steer_data0);
2108c2ecf20Sopenharmony_ci		*data1 = readq(&vp_reg->rts_access_steer_data1);
2118c2ecf20Sopenharmony_ci		*steer_ctrl = val64;
2128c2ecf20Sopenharmony_ci	} else
2138c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ciout:
2168c2ecf20Sopenharmony_ci	if (vpath->vp_open)
2178c2ecf20Sopenharmony_ci		spin_unlock(&vpath->lock);
2188c2ecf20Sopenharmony_ci	return status;
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cienum vxge_hw_status
2228c2ecf20Sopenharmony_civxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major,
2238c2ecf20Sopenharmony_ci			     u32 *minor, u32 *build)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
2268c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
2278c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[hldev->first_vp_id];
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
2328c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_ACTION,
2338c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_MEMO,
2348c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_OFFSET_READ,
2358c2ecf20Sopenharmony_ci				      &data0, &data1, &steer_ctrl);
2368c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
2378c2ecf20Sopenharmony_ci		return status;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	*major = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
2408c2ecf20Sopenharmony_ci	*minor = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
2418c2ecf20Sopenharmony_ci	*build = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return status;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
2498c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
2508c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
2518c2ecf20Sopenharmony_ci	u32 ret;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[hldev->first_vp_id];
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
2568c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_ACTION,
2578c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_MEMO,
2588c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_OFFSET_COMMIT,
2598c2ecf20Sopenharmony_ci				      &data0, &data1, &steer_ctrl);
2608c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
2618c2ecf20Sopenharmony_ci		vxge_debug_init(VXGE_ERR, "%s: FW upgrade failed", __func__);
2628c2ecf20Sopenharmony_ci		goto exit;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	ret = VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(steer_ctrl) & 0x7F;
2668c2ecf20Sopenharmony_ci	if (ret != 1) {
2678c2ecf20Sopenharmony_ci		vxge_debug_init(VXGE_ERR, "%s: FW commit failed with error %d",
2688c2ecf20Sopenharmony_ci				__func__, ret);
2698c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ciexit:
2738c2ecf20Sopenharmony_ci	return status;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cienum vxge_hw_status
2778c2ecf20Sopenharmony_civxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *fwdata, int size)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
2808c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
2818c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
2828c2ecf20Sopenharmony_ci	int ret_code, sec_code;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[hldev->first_vp_id];
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	/* send upgrade start command */
2878c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
2888c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_ACTION,
2898c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_MEMO,
2908c2ecf20Sopenharmony_ci				      VXGE_HW_FW_UPGRADE_OFFSET_START,
2918c2ecf20Sopenharmony_ci				      &data0, &data1, &steer_ctrl);
2928c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
2938c2ecf20Sopenharmony_ci		vxge_debug_init(VXGE_ERR, " %s: Upgrade start cmd failed",
2948c2ecf20Sopenharmony_ci				__func__);
2958c2ecf20Sopenharmony_ci		return status;
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	/* Transfer fw image to adapter 16 bytes at a time */
2998c2ecf20Sopenharmony_ci	for (; size > 0; size -= VXGE_HW_FW_UPGRADE_BLK_SIZE) {
3008c2ecf20Sopenharmony_ci		steer_ctrl = 0;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci		/* The next 128bits of fwdata to be loaded onto the adapter */
3038c2ecf20Sopenharmony_ci		data0 = *((u64 *)fwdata);
3048c2ecf20Sopenharmony_ci		data1 = *((u64 *)fwdata + 1);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci		status = vxge_hw_vpath_fw_api(vpath,
3078c2ecf20Sopenharmony_ci					      VXGE_HW_FW_UPGRADE_ACTION,
3088c2ecf20Sopenharmony_ci					      VXGE_HW_FW_UPGRADE_MEMO,
3098c2ecf20Sopenharmony_ci					      VXGE_HW_FW_UPGRADE_OFFSET_SEND,
3108c2ecf20Sopenharmony_ci					      &data0, &data1, &steer_ctrl);
3118c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK) {
3128c2ecf20Sopenharmony_ci			vxge_debug_init(VXGE_ERR, "%s: Upgrade send failed",
3138c2ecf20Sopenharmony_ci					__func__);
3148c2ecf20Sopenharmony_ci			goto out;
3158c2ecf20Sopenharmony_ci		}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci		ret_code = VXGE_HW_UPGRADE_GET_RET_ERR_CODE(data0);
3188c2ecf20Sopenharmony_ci		switch (ret_code) {
3198c2ecf20Sopenharmony_ci		case VXGE_HW_FW_UPGRADE_OK:
3208c2ecf20Sopenharmony_ci			/* All OK, send next 16 bytes. */
3218c2ecf20Sopenharmony_ci			break;
3228c2ecf20Sopenharmony_ci		case VXGE_FW_UPGRADE_BYTES2SKIP:
3238c2ecf20Sopenharmony_ci			/* skip bytes in the stream */
3248c2ecf20Sopenharmony_ci			fwdata += (data0 >> 8) & 0xFFFFFFFF;
3258c2ecf20Sopenharmony_ci			break;
3268c2ecf20Sopenharmony_ci		case VXGE_HW_FW_UPGRADE_DONE:
3278c2ecf20Sopenharmony_ci			goto out;
3288c2ecf20Sopenharmony_ci		case VXGE_HW_FW_UPGRADE_ERR:
3298c2ecf20Sopenharmony_ci			sec_code = VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(data0);
3308c2ecf20Sopenharmony_ci			switch (sec_code) {
3318c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1:
3328c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7:
3338c2ecf20Sopenharmony_ci				printk(KERN_ERR
3348c2ecf20Sopenharmony_ci				       "corrupted data from .ncf file\n");
3358c2ecf20Sopenharmony_ci				break;
3368c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3:
3378c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4:
3388c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5:
3398c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6:
3408c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8:
3418c2ecf20Sopenharmony_ci				printk(KERN_ERR "invalid .ncf file\n");
3428c2ecf20Sopenharmony_ci				break;
3438c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW:
3448c2ecf20Sopenharmony_ci				printk(KERN_ERR "buffer overflow\n");
3458c2ecf20Sopenharmony_ci				break;
3468c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH:
3478c2ecf20Sopenharmony_ci				printk(KERN_ERR "failed to flash the image\n");
3488c2ecf20Sopenharmony_ci				break;
3498c2ecf20Sopenharmony_ci			case VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN:
3508c2ecf20Sopenharmony_ci				printk(KERN_ERR
3518c2ecf20Sopenharmony_ci				       "generic error. Unknown error type\n");
3528c2ecf20Sopenharmony_ci				break;
3538c2ecf20Sopenharmony_ci			default:
3548c2ecf20Sopenharmony_ci				printk(KERN_ERR "Unknown error of type %d\n",
3558c2ecf20Sopenharmony_ci				       sec_code);
3568c2ecf20Sopenharmony_ci				break;
3578c2ecf20Sopenharmony_ci			}
3588c2ecf20Sopenharmony_ci			status = VXGE_HW_FAIL;
3598c2ecf20Sopenharmony_ci			goto out;
3608c2ecf20Sopenharmony_ci		default:
3618c2ecf20Sopenharmony_ci			printk(KERN_ERR "Unknown FW error: %d\n", ret_code);
3628c2ecf20Sopenharmony_ci			status = VXGE_HW_FAIL;
3638c2ecf20Sopenharmony_ci			goto out;
3648c2ecf20Sopenharmony_ci		}
3658c2ecf20Sopenharmony_ci		/* point to next 16 bytes */
3668c2ecf20Sopenharmony_ci		fwdata += VXGE_HW_FW_UPGRADE_BLK_SIZE;
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ciout:
3698c2ecf20Sopenharmony_ci	return status;
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cienum vxge_hw_status
3738c2ecf20Sopenharmony_civxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
3748c2ecf20Sopenharmony_ci				struct eprom_image *img)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
3778c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
3788c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
3798c2ecf20Sopenharmony_ci	int i;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[hldev->first_vp_id];
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) {
3848c2ecf20Sopenharmony_ci		data0 = VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(i);
3858c2ecf20Sopenharmony_ci		data1 = steer_ctrl = 0;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		status = vxge_hw_vpath_fw_api(vpath,
3888c2ecf20Sopenharmony_ci			VXGE_HW_FW_API_GET_EPROM_REV,
3898c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
3908c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
3918c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
3928c2ecf20Sopenharmony_ci			break;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		img[i].is_valid = VXGE_HW_GET_EPROM_IMAGE_VALID(data0);
3958c2ecf20Sopenharmony_ci		img[i].index = VXGE_HW_GET_EPROM_IMAGE_INDEX(data0);
3968c2ecf20Sopenharmony_ci		img[i].type = VXGE_HW_GET_EPROM_IMAGE_TYPE(data0);
3978c2ecf20Sopenharmony_ci		img[i].version = VXGE_HW_GET_EPROM_IMAGE_REV(data0);
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	return status;
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci/*
4048c2ecf20Sopenharmony_ci * __vxge_hw_channel_free - Free memory allocated for channel
4058c2ecf20Sopenharmony_ci * This function deallocates memory from the channel and various arrays
4068c2ecf20Sopenharmony_ci * in the channel
4078c2ecf20Sopenharmony_ci */
4088c2ecf20Sopenharmony_cistatic void __vxge_hw_channel_free(struct __vxge_hw_channel *channel)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	kfree(channel->work_arr);
4118c2ecf20Sopenharmony_ci	kfree(channel->free_arr);
4128c2ecf20Sopenharmony_ci	kfree(channel->reserve_arr);
4138c2ecf20Sopenharmony_ci	kfree(channel->orig_arr);
4148c2ecf20Sopenharmony_ci	kfree(channel);
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci/*
4188c2ecf20Sopenharmony_ci * __vxge_hw_channel_initialize - Initialize a channel
4198c2ecf20Sopenharmony_ci * This function initializes a channel by properly setting the
4208c2ecf20Sopenharmony_ci * various references
4218c2ecf20Sopenharmony_ci */
4228c2ecf20Sopenharmony_cistatic enum vxge_hw_status
4238c2ecf20Sopenharmony_ci__vxge_hw_channel_initialize(struct __vxge_hw_channel *channel)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	u32 i;
4268c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	vpath = channel->vph->vpath;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	if ((channel->reserve_arr != NULL) && (channel->orig_arr != NULL)) {
4318c2ecf20Sopenharmony_ci		for (i = 0; i < channel->length; i++)
4328c2ecf20Sopenharmony_ci			channel->orig_arr[i] = channel->reserve_arr[i];
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	switch (channel->type) {
4368c2ecf20Sopenharmony_ci	case VXGE_HW_CHANNEL_TYPE_FIFO:
4378c2ecf20Sopenharmony_ci		vpath->fifoh = (struct __vxge_hw_fifo *)channel;
4388c2ecf20Sopenharmony_ci		channel->stats = &((struct __vxge_hw_fifo *)
4398c2ecf20Sopenharmony_ci				channel)->stats->common_stats;
4408c2ecf20Sopenharmony_ci		break;
4418c2ecf20Sopenharmony_ci	case VXGE_HW_CHANNEL_TYPE_RING:
4428c2ecf20Sopenharmony_ci		vpath->ringh = (struct __vxge_hw_ring *)channel;
4438c2ecf20Sopenharmony_ci		channel->stats = &((struct __vxge_hw_ring *)
4448c2ecf20Sopenharmony_ci				channel)->stats->common_stats;
4458c2ecf20Sopenharmony_ci		break;
4468c2ecf20Sopenharmony_ci	default:
4478c2ecf20Sopenharmony_ci		break;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci/*
4548c2ecf20Sopenharmony_ci * __vxge_hw_channel_reset - Resets a channel
4558c2ecf20Sopenharmony_ci * This function resets a channel by properly setting the various references
4568c2ecf20Sopenharmony_ci */
4578c2ecf20Sopenharmony_cistatic enum vxge_hw_status
4588c2ecf20Sopenharmony_ci__vxge_hw_channel_reset(struct __vxge_hw_channel *channel)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	u32 i;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	for (i = 0; i < channel->length; i++) {
4638c2ecf20Sopenharmony_ci		if (channel->reserve_arr != NULL)
4648c2ecf20Sopenharmony_ci			channel->reserve_arr[i] = channel->orig_arr[i];
4658c2ecf20Sopenharmony_ci		if (channel->free_arr != NULL)
4668c2ecf20Sopenharmony_ci			channel->free_arr[i] = NULL;
4678c2ecf20Sopenharmony_ci		if (channel->work_arr != NULL)
4688c2ecf20Sopenharmony_ci			channel->work_arr[i] = NULL;
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci	channel->free_ptr = channel->length;
4718c2ecf20Sopenharmony_ci	channel->reserve_ptr = channel->length;
4728c2ecf20Sopenharmony_ci	channel->reserve_top = 0;
4738c2ecf20Sopenharmony_ci	channel->post_index = 0;
4748c2ecf20Sopenharmony_ci	channel->compl_index = 0;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci/*
4808c2ecf20Sopenharmony_ci * __vxge_hw_device_pci_e_init
4818c2ecf20Sopenharmony_ci * Initialize certain PCI/PCI-X configuration registers
4828c2ecf20Sopenharmony_ci * with recommended values. Save config space for future hw resets.
4838c2ecf20Sopenharmony_ci */
4848c2ecf20Sopenharmony_cistatic void __vxge_hw_device_pci_e_init(struct __vxge_hw_device *hldev)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	u16 cmd = 0;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	/* Set the PErr Repconse bit and SERR in PCI command register. */
4898c2ecf20Sopenharmony_ci	pci_read_config_word(hldev->pdev, PCI_COMMAND, &cmd);
4908c2ecf20Sopenharmony_ci	cmd |= 0x140;
4918c2ecf20Sopenharmony_ci	pci_write_config_word(hldev->pdev, PCI_COMMAND, cmd);
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	pci_save_state(hldev->pdev);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci/* __vxge_hw_device_vpath_reset_in_prog_check - Check if vpath reset
4978c2ecf20Sopenharmony_ci * in progress
4988c2ecf20Sopenharmony_ci * This routine checks the vpath reset in progress register is turned zero
4998c2ecf20Sopenharmony_ci */
5008c2ecf20Sopenharmony_cistatic enum vxge_hw_status
5018c2ecf20Sopenharmony_ci__vxge_hw_device_vpath_reset_in_prog_check(u64 __iomem *vpath_rst_in_prog)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
5048c2ecf20Sopenharmony_ci	status = __vxge_hw_device_register_poll(vpath_rst_in_prog,
5058c2ecf20Sopenharmony_ci			VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(0x1ffff),
5068c2ecf20Sopenharmony_ci			VXGE_HW_DEF_DEVICE_POLL_MILLIS);
5078c2ecf20Sopenharmony_ci	return status;
5088c2ecf20Sopenharmony_ci}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci/*
5118c2ecf20Sopenharmony_ci * _hw_legacy_swapper_set - Set the swapper bits for the legacy secion.
5128c2ecf20Sopenharmony_ci * Set the swapper bits appropriately for the lagacy section.
5138c2ecf20Sopenharmony_ci */
5148c2ecf20Sopenharmony_cistatic enum vxge_hw_status
5158c2ecf20Sopenharmony_ci__vxge_hw_legacy_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	u64 val64;
5188c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	val64 = readq(&legacy_reg->toc_swapper_fb);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	wmb();
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	switch (val64) {
5258c2ecf20Sopenharmony_ci	case VXGE_HW_SWAPPER_INITIAL_VALUE:
5268c2ecf20Sopenharmony_ci		return status;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	case VXGE_HW_SWAPPER_BYTE_SWAPPED_BIT_FLIPPED:
5298c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
5308c2ecf20Sopenharmony_ci			&legacy_reg->pifm_rd_swap_en);
5318c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
5328c2ecf20Sopenharmony_ci			&legacy_reg->pifm_rd_flip_en);
5338c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
5348c2ecf20Sopenharmony_ci			&legacy_reg->pifm_wr_swap_en);
5358c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
5368c2ecf20Sopenharmony_ci			&legacy_reg->pifm_wr_flip_en);
5378c2ecf20Sopenharmony_ci		break;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	case VXGE_HW_SWAPPER_BYTE_SWAPPED:
5408c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_READ_BYTE_SWAP_ENABLE,
5418c2ecf20Sopenharmony_ci			&legacy_reg->pifm_rd_swap_en);
5428c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE,
5438c2ecf20Sopenharmony_ci			&legacy_reg->pifm_wr_swap_en);
5448c2ecf20Sopenharmony_ci		break;
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	case VXGE_HW_SWAPPER_BIT_FLIPPED:
5478c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_READ_BIT_FLAP_ENABLE,
5488c2ecf20Sopenharmony_ci			&legacy_reg->pifm_rd_flip_en);
5498c2ecf20Sopenharmony_ci		writeq(VXGE_HW_SWAPPER_WRITE_BIT_FLAP_ENABLE,
5508c2ecf20Sopenharmony_ci			&legacy_reg->pifm_wr_flip_en);
5518c2ecf20Sopenharmony_ci		break;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	wmb();
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	val64 = readq(&legacy_reg->toc_swapper_fb);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	if (val64 != VXGE_HW_SWAPPER_INITIAL_VALUE)
5598c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_SWAPPER_CTRL;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	return status;
5628c2ecf20Sopenharmony_ci}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci/*
5658c2ecf20Sopenharmony_ci * __vxge_hw_device_toc_get
5668c2ecf20Sopenharmony_ci * This routine sets the swapper and reads the toc pointer and returns the
5678c2ecf20Sopenharmony_ci * memory mapped address of the toc
5688c2ecf20Sopenharmony_ci */
5698c2ecf20Sopenharmony_cistatic struct vxge_hw_toc_reg __iomem *
5708c2ecf20Sopenharmony_ci__vxge_hw_device_toc_get(void __iomem *bar0)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	u64 val64;
5738c2ecf20Sopenharmony_ci	struct vxge_hw_toc_reg __iomem *toc = NULL;
5748c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	struct vxge_hw_legacy_reg __iomem *legacy_reg =
5778c2ecf20Sopenharmony_ci		(struct vxge_hw_legacy_reg __iomem *)bar0;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	status = __vxge_hw_legacy_swapper_set(legacy_reg);
5808c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
5818c2ecf20Sopenharmony_ci		goto exit;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	val64 =	readq(&legacy_reg->toc_first_pointer);
5848c2ecf20Sopenharmony_ci	toc = bar0 + val64;
5858c2ecf20Sopenharmony_ciexit:
5868c2ecf20Sopenharmony_ci	return toc;
5878c2ecf20Sopenharmony_ci}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci/*
5908c2ecf20Sopenharmony_ci * __vxge_hw_device_reg_addr_get
5918c2ecf20Sopenharmony_ci * This routine sets the swapper and reads the toc pointer and initializes the
5928c2ecf20Sopenharmony_ci * register location pointers in the device object. It waits until the ric is
5938c2ecf20Sopenharmony_ci * completed initializing registers.
5948c2ecf20Sopenharmony_ci */
5958c2ecf20Sopenharmony_cistatic enum vxge_hw_status
5968c2ecf20Sopenharmony_ci__vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
5978c2ecf20Sopenharmony_ci{
5988c2ecf20Sopenharmony_ci	u64 val64;
5998c2ecf20Sopenharmony_ci	u32 i;
6008c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	hldev->legacy_reg = hldev->bar0;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	hldev->toc_reg = __vxge_hw_device_toc_get(hldev->bar0);
6058c2ecf20Sopenharmony_ci	if (hldev->toc_reg  == NULL) {
6068c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
6078c2ecf20Sopenharmony_ci		goto exit;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	val64 = readq(&hldev->toc_reg->toc_common_pointer);
6118c2ecf20Sopenharmony_ci	hldev->common_reg = hldev->bar0 + val64;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	val64 = readq(&hldev->toc_reg->toc_mrpcim_pointer);
6148c2ecf20Sopenharmony_ci	hldev->mrpcim_reg = hldev->bar0 + val64;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_TITAN_SRPCIM_REG_SPACES; i++) {
6178c2ecf20Sopenharmony_ci		val64 = readq(&hldev->toc_reg->toc_srpcim_pointer[i]);
6188c2ecf20Sopenharmony_ci		hldev->srpcim_reg[i] = hldev->bar0 + val64;
6198c2ecf20Sopenharmony_ci	}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_TITAN_VPMGMT_REG_SPACES; i++) {
6228c2ecf20Sopenharmony_ci		val64 = readq(&hldev->toc_reg->toc_vpmgmt_pointer[i]);
6238c2ecf20Sopenharmony_ci		hldev->vpmgmt_reg[i] = hldev->bar0 + val64;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_TITAN_VPATH_REG_SPACES; i++) {
6278c2ecf20Sopenharmony_ci		val64 = readq(&hldev->toc_reg->toc_vpath_pointer[i]);
6288c2ecf20Sopenharmony_ci		hldev->vpath_reg[i] = hldev->bar0 + val64;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	val64 = readq(&hldev->toc_reg->toc_kdfc);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	switch (VXGE_HW_TOC_GET_KDFC_INITIAL_BIR(val64)) {
6348c2ecf20Sopenharmony_ci	case 0:
6358c2ecf20Sopenharmony_ci		hldev->kdfc = hldev->bar0 + VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64) ;
6368c2ecf20Sopenharmony_ci		break;
6378c2ecf20Sopenharmony_ci	default:
6388c2ecf20Sopenharmony_ci		break;
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	status = __vxge_hw_device_vpath_reset_in_prog_check(
6428c2ecf20Sopenharmony_ci			(u64 __iomem *)&hldev->common_reg->vpath_rst_in_prog);
6438c2ecf20Sopenharmony_ciexit:
6448c2ecf20Sopenharmony_ci	return status;
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci/*
6488c2ecf20Sopenharmony_ci * __vxge_hw_device_access_rights_get: Get Access Rights of the driver
6498c2ecf20Sopenharmony_ci * This routine returns the Access Rights of the driver
6508c2ecf20Sopenharmony_ci */
6518c2ecf20Sopenharmony_cistatic u32
6528c2ecf20Sopenharmony_ci__vxge_hw_device_access_rights_get(u32 host_type, u32 func_id)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	u32 access_rights = VXGE_HW_DEVICE_ACCESS_RIGHT_VPATH;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	switch (host_type) {
6578c2ecf20Sopenharmony_ci	case VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION:
6588c2ecf20Sopenharmony_ci		if (func_id == 0) {
6598c2ecf20Sopenharmony_ci			access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
6608c2ecf20Sopenharmony_ci					VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
6618c2ecf20Sopenharmony_ci		}
6628c2ecf20Sopenharmony_ci		break;
6638c2ecf20Sopenharmony_ci	case VXGE_HW_MR_NO_SR_VH0_BASE_FUNCTION:
6648c2ecf20Sopenharmony_ci		access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
6658c2ecf20Sopenharmony_ci				VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
6668c2ecf20Sopenharmony_ci		break;
6678c2ecf20Sopenharmony_ci	case VXGE_HW_NO_MR_SR_VH0_FUNCTION0:
6688c2ecf20Sopenharmony_ci		access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
6698c2ecf20Sopenharmony_ci				VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
6708c2ecf20Sopenharmony_ci		break;
6718c2ecf20Sopenharmony_ci	case VXGE_HW_NO_MR_SR_VH0_VIRTUAL_FUNCTION:
6728c2ecf20Sopenharmony_ci	case VXGE_HW_SR_VH_VIRTUAL_FUNCTION:
6738c2ecf20Sopenharmony_ci	case VXGE_HW_MR_SR_VH0_INVALID_CONFIG:
6748c2ecf20Sopenharmony_ci		break;
6758c2ecf20Sopenharmony_ci	case VXGE_HW_SR_VH_FUNCTION0:
6768c2ecf20Sopenharmony_ci	case VXGE_HW_VH_NORMAL_FUNCTION:
6778c2ecf20Sopenharmony_ci		access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
6788c2ecf20Sopenharmony_ci		break;
6798c2ecf20Sopenharmony_ci	}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	return access_rights;
6828c2ecf20Sopenharmony_ci}
6838c2ecf20Sopenharmony_ci/*
6848c2ecf20Sopenharmony_ci * __vxge_hw_device_is_privilaged
6858c2ecf20Sopenharmony_ci * This routine checks if the device function is privilaged or not
6868c2ecf20Sopenharmony_ci */
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cienum vxge_hw_status
6898c2ecf20Sopenharmony_ci__vxge_hw_device_is_privilaged(u32 host_type, u32 func_id)
6908c2ecf20Sopenharmony_ci{
6918c2ecf20Sopenharmony_ci	if (__vxge_hw_device_access_rights_get(host_type,
6928c2ecf20Sopenharmony_ci		func_id) &
6938c2ecf20Sopenharmony_ci		VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)
6948c2ecf20Sopenharmony_ci		return VXGE_HW_OK;
6958c2ecf20Sopenharmony_ci	else
6968c2ecf20Sopenharmony_ci		return VXGE_HW_ERR_PRIVILEGED_OPERATION;
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci/*
7008c2ecf20Sopenharmony_ci * __vxge_hw_vpath_func_id_get - Get the function id of the vpath.
7018c2ecf20Sopenharmony_ci * Returns the function number of the vpath.
7028c2ecf20Sopenharmony_ci */
7038c2ecf20Sopenharmony_cistatic u32
7048c2ecf20Sopenharmony_ci__vxge_hw_vpath_func_id_get(struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg)
7058c2ecf20Sopenharmony_ci{
7068c2ecf20Sopenharmony_ci	u64 val64;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	val64 = readq(&vpmgmt_reg->vpath_to_func_map_cfg1);
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	return
7118c2ecf20Sopenharmony_ci	 (u32)VXGE_HW_VPATH_TO_FUNC_MAP_CFG1_GET_VPATH_TO_FUNC_MAP_CFG1(val64);
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci/*
7158c2ecf20Sopenharmony_ci * __vxge_hw_device_host_info_get
7168c2ecf20Sopenharmony_ci * This routine returns the host type assignments
7178c2ecf20Sopenharmony_ci */
7188c2ecf20Sopenharmony_cistatic void __vxge_hw_device_host_info_get(struct __vxge_hw_device *hldev)
7198c2ecf20Sopenharmony_ci{
7208c2ecf20Sopenharmony_ci	u64 val64;
7218c2ecf20Sopenharmony_ci	u32 i;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	val64 = readq(&hldev->common_reg->host_type_assignments);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	hldev->host_type =
7268c2ecf20Sopenharmony_ci	   (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	hldev->vpath_assignments = readq(&hldev->common_reg->vpath_assignments);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
7318c2ecf20Sopenharmony_ci		if (!(hldev->vpath_assignments & vxge_mBIT(i)))
7328c2ecf20Sopenharmony_ci			continue;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		hldev->func_id =
7358c2ecf20Sopenharmony_ci			__vxge_hw_vpath_func_id_get(hldev->vpmgmt_reg[i]);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci		hldev->access_rights = __vxge_hw_device_access_rights_get(
7388c2ecf20Sopenharmony_ci			hldev->host_type, hldev->func_id);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci		hldev->virtual_paths[i].vp_open = VXGE_HW_VP_NOT_OPEN;
7418c2ecf20Sopenharmony_ci		hldev->virtual_paths[i].vp_reg = hldev->vpath_reg[i];
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci		hldev->first_vp_id = i;
7448c2ecf20Sopenharmony_ci		break;
7458c2ecf20Sopenharmony_ci	}
7468c2ecf20Sopenharmony_ci}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci/*
7498c2ecf20Sopenharmony_ci * __vxge_hw_verify_pci_e_info - Validate the pci-e link parameters such as
7508c2ecf20Sopenharmony_ci * link width and signalling rate.
7518c2ecf20Sopenharmony_ci */
7528c2ecf20Sopenharmony_cistatic enum vxge_hw_status
7538c2ecf20Sopenharmony_ci__vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
7548c2ecf20Sopenharmony_ci{
7558c2ecf20Sopenharmony_ci	struct pci_dev *dev = hldev->pdev;
7568c2ecf20Sopenharmony_ci	u16 lnk;
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	/* Get the negotiated link width and speed from PCI config space */
7598c2ecf20Sopenharmony_ci	pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnk);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	if ((lnk & PCI_EXP_LNKSTA_CLS) != 1)
7628c2ecf20Sopenharmony_ci		return VXGE_HW_ERR_INVALID_PCI_INFO;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	switch ((lnk & PCI_EXP_LNKSTA_NLW) >> 4) {
7658c2ecf20Sopenharmony_ci	case PCIE_LNK_WIDTH_RESRV:
7668c2ecf20Sopenharmony_ci	case PCIE_LNK_X1:
7678c2ecf20Sopenharmony_ci	case PCIE_LNK_X2:
7688c2ecf20Sopenharmony_ci	case PCIE_LNK_X4:
7698c2ecf20Sopenharmony_ci	case PCIE_LNK_X8:
7708c2ecf20Sopenharmony_ci		break;
7718c2ecf20Sopenharmony_ci	default:
7728c2ecf20Sopenharmony_ci		return VXGE_HW_ERR_INVALID_PCI_INFO;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci/*
7798c2ecf20Sopenharmony_ci * __vxge_hw_device_initialize
7808c2ecf20Sopenharmony_ci * Initialize Titan-V hardware.
7818c2ecf20Sopenharmony_ci */
7828c2ecf20Sopenharmony_cistatic enum vxge_hw_status
7838c2ecf20Sopenharmony_ci__vxge_hw_device_initialize(struct __vxge_hw_device *hldev)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	if (VXGE_HW_OK == __vxge_hw_device_is_privilaged(hldev->host_type,
7888c2ecf20Sopenharmony_ci				hldev->func_id)) {
7898c2ecf20Sopenharmony_ci		/* Validate the pci-e link width and speed */
7908c2ecf20Sopenharmony_ci		status = __vxge_hw_verify_pci_e_info(hldev);
7918c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
7928c2ecf20Sopenharmony_ci			goto exit;
7938c2ecf20Sopenharmony_ci	}
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ciexit:
7968c2ecf20Sopenharmony_ci	return status;
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci/*
8008c2ecf20Sopenharmony_ci * __vxge_hw_vpath_fw_ver_get - Get the fw version
8018c2ecf20Sopenharmony_ci * Returns FW Version
8028c2ecf20Sopenharmony_ci */
8038c2ecf20Sopenharmony_cistatic enum vxge_hw_status
8048c2ecf20Sopenharmony_ci__vxge_hw_vpath_fw_ver_get(struct __vxge_hw_virtualpath *vpath,
8058c2ecf20Sopenharmony_ci			   struct vxge_hw_device_hw_info *hw_info)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	struct vxge_hw_device_version *fw_version = &hw_info->fw_version;
8088c2ecf20Sopenharmony_ci	struct vxge_hw_device_date *fw_date = &hw_info->fw_date;
8098c2ecf20Sopenharmony_ci	struct vxge_hw_device_version *flash_version = &hw_info->flash_version;
8108c2ecf20Sopenharmony_ci	struct vxge_hw_device_date *flash_date = &hw_info->flash_date;
8118c2ecf20Sopenharmony_ci	u64 data0 = 0, data1 = 0, steer_ctrl = 0;
8128c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
8158c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
8168c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
8178c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
8188c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
8198c2ecf20Sopenharmony_ci		goto exit;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	fw_date->day =
8228c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_DAY(data0);
8238c2ecf20Sopenharmony_ci	fw_date->month =
8248c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MONTH(data0);
8258c2ecf20Sopenharmony_ci	fw_date->year =
8268c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_YEAR(data0);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	snprintf(fw_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
8298c2ecf20Sopenharmony_ci		 fw_date->month, fw_date->day, fw_date->year);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	fw_version->major =
8328c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
8338c2ecf20Sopenharmony_ci	fw_version->minor =
8348c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
8358c2ecf20Sopenharmony_ci	fw_version->build =
8368c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	snprintf(fw_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
8398c2ecf20Sopenharmony_ci		 fw_version->major, fw_version->minor, fw_version->build);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	flash_date->day =
8428c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_DAY(data1);
8438c2ecf20Sopenharmony_ci	flash_date->month =
8448c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MONTH(data1);
8458c2ecf20Sopenharmony_ci	flash_date->year =
8468c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_YEAR(data1);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	snprintf(flash_date->date, VXGE_HW_FW_STRLEN, "%2.2d/%2.2d/%4.4d",
8498c2ecf20Sopenharmony_ci		 flash_date->month, flash_date->day, flash_date->year);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	flash_version->major =
8528c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MAJOR(data1);
8538c2ecf20Sopenharmony_ci	flash_version->minor =
8548c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_MINOR(data1);
8558c2ecf20Sopenharmony_ci	flash_version->build =
8568c2ecf20Sopenharmony_ci	    (u32) VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_FLASH_VER_BUILD(data1);
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	snprintf(flash_version->version, VXGE_HW_FW_STRLEN, "%d.%d.%d",
8598c2ecf20Sopenharmony_ci		 flash_version->major, flash_version->minor,
8608c2ecf20Sopenharmony_ci		 flash_version->build);
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ciexit:
8638c2ecf20Sopenharmony_ci	return status;
8648c2ecf20Sopenharmony_ci}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci/*
8678c2ecf20Sopenharmony_ci * __vxge_hw_vpath_card_info_get - Get the serial numbers,
8688c2ecf20Sopenharmony_ci * part number and product description.
8698c2ecf20Sopenharmony_ci */
8708c2ecf20Sopenharmony_cistatic enum vxge_hw_status
8718c2ecf20Sopenharmony_ci__vxge_hw_vpath_card_info_get(struct __vxge_hw_virtualpath *vpath,
8728c2ecf20Sopenharmony_ci			      struct vxge_hw_device_hw_info *hw_info)
8738c2ecf20Sopenharmony_ci{
8748c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
8758c2ecf20Sopenharmony_ci	u64 data0, data1 = 0, steer_ctrl = 0;
8768c2ecf20Sopenharmony_ci	u8 *serial_number = hw_info->serial_number;
8778c2ecf20Sopenharmony_ci	u8 *part_number = hw_info->part_number;
8788c2ecf20Sopenharmony_ci	u8 *product_desc = hw_info->product_desc;
8798c2ecf20Sopenharmony_ci	u32 i, j = 0;
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci	data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_SERIAL_NUMBER;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
8848c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
8858c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
8868c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
8878c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
8888c2ecf20Sopenharmony_ci		return status;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	((u64 *)serial_number)[0] = be64_to_cpu(data0);
8918c2ecf20Sopenharmony_ci	((u64 *)serial_number)[1] = be64_to_cpu(data1);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_PART_NUMBER;
8948c2ecf20Sopenharmony_ci	data1 = steer_ctrl = 0;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
8978c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
8988c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
8998c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
9008c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
9018c2ecf20Sopenharmony_ci		return status;
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	((u64 *)part_number)[0] = be64_to_cpu(data0);
9048c2ecf20Sopenharmony_ci	((u64 *)part_number)[1] = be64_to_cpu(data1);
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	for (i = VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_0;
9078c2ecf20Sopenharmony_ci	     i <= VXGE_HW_RTS_ACCESS_STEER_DATA0_MEMO_ITEM_DESC_3; i++) {
9088c2ecf20Sopenharmony_ci		data0 = i;
9098c2ecf20Sopenharmony_ci		data1 = steer_ctrl = 0;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		status = vxge_hw_vpath_fw_api(vpath,
9128c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_MEMO_ENTRY,
9138c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
9148c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
9158c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
9168c2ecf20Sopenharmony_ci			return status;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci		((u64 *)product_desc)[j++] = be64_to_cpu(data0);
9198c2ecf20Sopenharmony_ci		((u64 *)product_desc)[j++] = be64_to_cpu(data1);
9208c2ecf20Sopenharmony_ci	}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	return status;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci/*
9268c2ecf20Sopenharmony_ci * __vxge_hw_vpath_pci_func_mode_get - Get the pci mode
9278c2ecf20Sopenharmony_ci * Returns pci function mode
9288c2ecf20Sopenharmony_ci */
9298c2ecf20Sopenharmony_cistatic enum vxge_hw_status
9308c2ecf20Sopenharmony_ci__vxge_hw_vpath_pci_func_mode_get(struct __vxge_hw_virtualpath *vpath,
9318c2ecf20Sopenharmony_ci				  struct vxge_hw_device_hw_info *hw_info)
9328c2ecf20Sopenharmony_ci{
9338c2ecf20Sopenharmony_ci	u64 data0, data1 = 0, steer_ctrl = 0;
9348c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	data0 = 0;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
9398c2ecf20Sopenharmony_ci			VXGE_HW_FW_API_GET_FUNC_MODE,
9408c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
9418c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
9428c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
9438c2ecf20Sopenharmony_ci		return status;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	hw_info->function_mode = VXGE_HW_GET_FUNC_MODE_VAL(data0);
9468c2ecf20Sopenharmony_ci	return status;
9478c2ecf20Sopenharmony_ci}
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci/*
9508c2ecf20Sopenharmony_ci * __vxge_hw_vpath_addr_get - Get the hw address entry for this vpath
9518c2ecf20Sopenharmony_ci *               from MAC address table.
9528c2ecf20Sopenharmony_ci */
9538c2ecf20Sopenharmony_cistatic enum vxge_hw_status
9548c2ecf20Sopenharmony_ci__vxge_hw_vpath_addr_get(struct __vxge_hw_virtualpath *vpath,
9558c2ecf20Sopenharmony_ci			 u8 *macaddr, u8 *macaddr_mask)
9568c2ecf20Sopenharmony_ci{
9578c2ecf20Sopenharmony_ci	u64 action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY,
9588c2ecf20Sopenharmony_ci	    data0 = 0, data1 = 0, steer_ctrl = 0;
9598c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
9608c2ecf20Sopenharmony_ci	int i;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	do {
9638c2ecf20Sopenharmony_ci		status = vxge_hw_vpath_fw_api(vpath, action,
9648c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
9658c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
9668c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
9678c2ecf20Sopenharmony_ci			goto exit;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci		data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data0);
9708c2ecf20Sopenharmony_ci		data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(
9718c2ecf20Sopenharmony_ci									data1);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci		for (i = ETH_ALEN; i > 0; i--) {
9748c2ecf20Sopenharmony_ci			macaddr[i - 1] = (u8) (data0 & 0xFF);
9758c2ecf20Sopenharmony_ci			data0 >>= 8;
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci			macaddr_mask[i - 1] = (u8) (data1 & 0xFF);
9788c2ecf20Sopenharmony_ci			data1 >>= 8;
9798c2ecf20Sopenharmony_ci		}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci		action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY;
9828c2ecf20Sopenharmony_ci		data0 = 0, data1 = 0, steer_ctrl = 0;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	} while (!is_valid_ether_addr(macaddr));
9858c2ecf20Sopenharmony_ciexit:
9868c2ecf20Sopenharmony_ci	return status;
9878c2ecf20Sopenharmony_ci}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci/**
9908c2ecf20Sopenharmony_ci * vxge_hw_device_hw_info_get - Get the hw information
9918c2ecf20Sopenharmony_ci * @bar0: the bar
9928c2ecf20Sopenharmony_ci * @hw_info: the hw_info struct
9938c2ecf20Sopenharmony_ci *
9948c2ecf20Sopenharmony_ci * Returns the vpath mask that has the bits set for each vpath allocated
9958c2ecf20Sopenharmony_ci * for the driver, FW version information, and the first mac address for
9968c2ecf20Sopenharmony_ci * each vpath
9978c2ecf20Sopenharmony_ci */
9988c2ecf20Sopenharmony_cienum vxge_hw_status
9998c2ecf20Sopenharmony_civxge_hw_device_hw_info_get(void __iomem *bar0,
10008c2ecf20Sopenharmony_ci			   struct vxge_hw_device_hw_info *hw_info)
10018c2ecf20Sopenharmony_ci{
10028c2ecf20Sopenharmony_ci	u32 i;
10038c2ecf20Sopenharmony_ci	u64 val64;
10048c2ecf20Sopenharmony_ci	struct vxge_hw_toc_reg __iomem *toc;
10058c2ecf20Sopenharmony_ci	struct vxge_hw_mrpcim_reg __iomem *mrpcim_reg;
10068c2ecf20Sopenharmony_ci	struct vxge_hw_common_reg __iomem *common_reg;
10078c2ecf20Sopenharmony_ci	struct vxge_hw_vpmgmt_reg __iomem *vpmgmt_reg;
10088c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
10098c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath vpath;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	memset(hw_info, 0, sizeof(struct vxge_hw_device_hw_info));
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	toc = __vxge_hw_device_toc_get(bar0);
10148c2ecf20Sopenharmony_ci	if (toc == NULL) {
10158c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_CRITICAL;
10168c2ecf20Sopenharmony_ci		goto exit;
10178c2ecf20Sopenharmony_ci	}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	val64 = readq(&toc->toc_common_pointer);
10208c2ecf20Sopenharmony_ci	common_reg = bar0 + val64;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	status = __vxge_hw_device_vpath_reset_in_prog_check(
10238c2ecf20Sopenharmony_ci		(u64 __iomem *)&common_reg->vpath_rst_in_prog);
10248c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
10258c2ecf20Sopenharmony_ci		goto exit;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	hw_info->vpath_mask = readq(&common_reg->vpath_assignments);
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	val64 = readq(&common_reg->host_type_assignments);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	hw_info->host_type =
10328c2ecf20Sopenharmony_ci	   (u32)VXGE_HW_HOST_TYPE_ASSIGNMENTS_GET_HOST_TYPE_ASSIGNMENTS(val64);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
10358c2ecf20Sopenharmony_ci		if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
10368c2ecf20Sopenharmony_ci			continue;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci		val64 = readq(&toc->toc_vpmgmt_pointer[i]);
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci		vpmgmt_reg = bar0 + val64;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci		hw_info->func_id = __vxge_hw_vpath_func_id_get(vpmgmt_reg);
10438c2ecf20Sopenharmony_ci		if (__vxge_hw_device_access_rights_get(hw_info->host_type,
10448c2ecf20Sopenharmony_ci			hw_info->func_id) &
10458c2ecf20Sopenharmony_ci			VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM) {
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci			val64 = readq(&toc->toc_mrpcim_pointer);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci			mrpcim_reg = bar0 + val64;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci			writeq(0, &mrpcim_reg->xgmac_gen_fw_memo_mask);
10528c2ecf20Sopenharmony_ci			wmb();
10538c2ecf20Sopenharmony_ci		}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci		val64 = readq(&toc->toc_vpath_pointer[i]);
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci		spin_lock_init(&vpath.lock);
10588c2ecf20Sopenharmony_ci		vpath.vp_reg = bar0 + val64;
10598c2ecf20Sopenharmony_ci		vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_pci_func_mode_get(&vpath, hw_info);
10628c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
10638c2ecf20Sopenharmony_ci			goto exit;
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_fw_ver_get(&vpath, hw_info);
10668c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
10678c2ecf20Sopenharmony_ci			goto exit;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_card_info_get(&vpath, hw_info);
10708c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
10718c2ecf20Sopenharmony_ci			goto exit;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci		break;
10748c2ecf20Sopenharmony_ci	}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
10778c2ecf20Sopenharmony_ci		if (!((hw_info->vpath_mask) & vxge_mBIT(i)))
10788c2ecf20Sopenharmony_ci			continue;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci		val64 = readq(&toc->toc_vpath_pointer[i]);
10818c2ecf20Sopenharmony_ci		vpath.vp_reg = bar0 + val64;
10828c2ecf20Sopenharmony_ci		vpath.vp_open = VXGE_HW_VP_NOT_OPEN;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci		status =  __vxge_hw_vpath_addr_get(&vpath,
10858c2ecf20Sopenharmony_ci				hw_info->mac_addrs[i],
10868c2ecf20Sopenharmony_ci				hw_info->mac_addr_masks[i]);
10878c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
10888c2ecf20Sopenharmony_ci			goto exit;
10898c2ecf20Sopenharmony_ci	}
10908c2ecf20Sopenharmony_ciexit:
10918c2ecf20Sopenharmony_ci	return status;
10928c2ecf20Sopenharmony_ci}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci/*
10958c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_destroy - Deallocates the block pool
10968c2ecf20Sopenharmony_ci */
10978c2ecf20Sopenharmony_cistatic void __vxge_hw_blockpool_destroy(struct __vxge_hw_blockpool *blockpool)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev;
11008c2ecf20Sopenharmony_ci	struct list_head *p, *n;
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	if (!blockpool)
11038c2ecf20Sopenharmony_ci		return;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	hldev = blockpool->hldev;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	list_for_each_safe(p, n, &blockpool->free_block_list) {
11088c2ecf20Sopenharmony_ci		dma_unmap_single(&hldev->pdev->dev,
11098c2ecf20Sopenharmony_ci				 ((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
11108c2ecf20Sopenharmony_ci				 ((struct __vxge_hw_blockpool_entry *)p)->length,
11118c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci		vxge_os_dma_free(hldev->pdev,
11148c2ecf20Sopenharmony_ci			((struct __vxge_hw_blockpool_entry *)p)->memblock,
11158c2ecf20Sopenharmony_ci			&((struct __vxge_hw_blockpool_entry *)p)->acc_handle);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
11188c2ecf20Sopenharmony_ci		kfree(p);
11198c2ecf20Sopenharmony_ci		blockpool->pool_size--;
11208c2ecf20Sopenharmony_ci	}
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	list_for_each_safe(p, n, &blockpool->free_entry_list) {
11238c2ecf20Sopenharmony_ci		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
11248c2ecf20Sopenharmony_ci		kfree((void *)p);
11258c2ecf20Sopenharmony_ci	}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	return;
11288c2ecf20Sopenharmony_ci}
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci/*
11318c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_create - Create block pool
11328c2ecf20Sopenharmony_ci */
11338c2ecf20Sopenharmony_cistatic enum vxge_hw_status
11348c2ecf20Sopenharmony_ci__vxge_hw_blockpool_create(struct __vxge_hw_device *hldev,
11358c2ecf20Sopenharmony_ci			   struct __vxge_hw_blockpool *blockpool,
11368c2ecf20Sopenharmony_ci			   u32 pool_size,
11378c2ecf20Sopenharmony_ci			   u32 pool_max)
11388c2ecf20Sopenharmony_ci{
11398c2ecf20Sopenharmony_ci	u32 i;
11408c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool_entry *entry = NULL;
11418c2ecf20Sopenharmony_ci	void *memblock;
11428c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
11438c2ecf20Sopenharmony_ci	struct pci_dev *dma_handle;
11448c2ecf20Sopenharmony_ci	struct pci_dev *acc_handle;
11458c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	if (blockpool == NULL) {
11488c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
11498c2ecf20Sopenharmony_ci		goto blockpool_create_exit;
11508c2ecf20Sopenharmony_ci	}
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci	blockpool->hldev = hldev;
11538c2ecf20Sopenharmony_ci	blockpool->block_size = VXGE_HW_BLOCK_SIZE;
11548c2ecf20Sopenharmony_ci	blockpool->pool_size = 0;
11558c2ecf20Sopenharmony_ci	blockpool->pool_max = pool_max;
11568c2ecf20Sopenharmony_ci	blockpool->req_out = 0;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&blockpool->free_block_list);
11598c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&blockpool->free_entry_list);
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	for (i = 0; i < pool_size + pool_max; i++) {
11628c2ecf20Sopenharmony_ci		entry = kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
11638c2ecf20Sopenharmony_ci				GFP_KERNEL);
11648c2ecf20Sopenharmony_ci		if (entry == NULL) {
11658c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_destroy(blockpool);
11668c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
11678c2ecf20Sopenharmony_ci			goto blockpool_create_exit;
11688c2ecf20Sopenharmony_ci		}
11698c2ecf20Sopenharmony_ci		list_add(&entry->item, &blockpool->free_entry_list);
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	for (i = 0; i < pool_size; i++) {
11738c2ecf20Sopenharmony_ci		memblock = vxge_os_dma_malloc(
11748c2ecf20Sopenharmony_ci				hldev->pdev,
11758c2ecf20Sopenharmony_ci				VXGE_HW_BLOCK_SIZE,
11768c2ecf20Sopenharmony_ci				&dma_handle,
11778c2ecf20Sopenharmony_ci				&acc_handle);
11788c2ecf20Sopenharmony_ci		if (memblock == NULL) {
11798c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_destroy(blockpool);
11808c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
11818c2ecf20Sopenharmony_ci			goto blockpool_create_exit;
11828c2ecf20Sopenharmony_ci		}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci		dma_addr = dma_map_single(&hldev->pdev->dev, memblock,
11858c2ecf20Sopenharmony_ci					  VXGE_HW_BLOCK_SIZE,
11868c2ecf20Sopenharmony_ci					  DMA_BIDIRECTIONAL);
11878c2ecf20Sopenharmony_ci		if (unlikely(dma_mapping_error(&hldev->pdev->dev, dma_addr))) {
11888c2ecf20Sopenharmony_ci			vxge_os_dma_free(hldev->pdev, memblock, &acc_handle);
11898c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_destroy(blockpool);
11908c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
11918c2ecf20Sopenharmony_ci			goto blockpool_create_exit;
11928c2ecf20Sopenharmony_ci		}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci		if (!list_empty(&blockpool->free_entry_list))
11958c2ecf20Sopenharmony_ci			entry = (struct __vxge_hw_blockpool_entry *)
11968c2ecf20Sopenharmony_ci				list_first_entry(&blockpool->free_entry_list,
11978c2ecf20Sopenharmony_ci					struct __vxge_hw_blockpool_entry,
11988c2ecf20Sopenharmony_ci					item);
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci		if (entry == NULL)
12018c2ecf20Sopenharmony_ci			entry =
12028c2ecf20Sopenharmony_ci			    kzalloc(sizeof(struct __vxge_hw_blockpool_entry),
12038c2ecf20Sopenharmony_ci					GFP_KERNEL);
12048c2ecf20Sopenharmony_ci		if (entry != NULL) {
12058c2ecf20Sopenharmony_ci			list_del(&entry->item);
12068c2ecf20Sopenharmony_ci			entry->length = VXGE_HW_BLOCK_SIZE;
12078c2ecf20Sopenharmony_ci			entry->memblock = memblock;
12088c2ecf20Sopenharmony_ci			entry->dma_addr = dma_addr;
12098c2ecf20Sopenharmony_ci			entry->acc_handle = acc_handle;
12108c2ecf20Sopenharmony_ci			entry->dma_handle = dma_handle;
12118c2ecf20Sopenharmony_ci			list_add(&entry->item,
12128c2ecf20Sopenharmony_ci					  &blockpool->free_block_list);
12138c2ecf20Sopenharmony_ci			blockpool->pool_size++;
12148c2ecf20Sopenharmony_ci		} else {
12158c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_destroy(blockpool);
12168c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
12178c2ecf20Sopenharmony_ci			goto blockpool_create_exit;
12188c2ecf20Sopenharmony_ci		}
12198c2ecf20Sopenharmony_ci	}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ciblockpool_create_exit:
12228c2ecf20Sopenharmony_ci	return status;
12238c2ecf20Sopenharmony_ci}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci/*
12268c2ecf20Sopenharmony_ci * __vxge_hw_device_fifo_config_check - Check fifo configuration.
12278c2ecf20Sopenharmony_ci * Check the fifo configuration
12288c2ecf20Sopenharmony_ci */
12298c2ecf20Sopenharmony_cistatic enum vxge_hw_status
12308c2ecf20Sopenharmony_ci__vxge_hw_device_fifo_config_check(struct vxge_hw_fifo_config *fifo_config)
12318c2ecf20Sopenharmony_ci{
12328c2ecf20Sopenharmony_ci	if ((fifo_config->fifo_blocks < VXGE_HW_MIN_FIFO_BLOCKS) ||
12338c2ecf20Sopenharmony_ci	    (fifo_config->fifo_blocks > VXGE_HW_MAX_FIFO_BLOCKS))
12348c2ecf20Sopenharmony_ci		return VXGE_HW_BADCFG_FIFO_BLOCKS;
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
12378c2ecf20Sopenharmony_ci}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci/*
12408c2ecf20Sopenharmony_ci * __vxge_hw_device_vpath_config_check - Check vpath configuration.
12418c2ecf20Sopenharmony_ci * Check the vpath configuration
12428c2ecf20Sopenharmony_ci */
12438c2ecf20Sopenharmony_cistatic enum vxge_hw_status
12448c2ecf20Sopenharmony_ci__vxge_hw_device_vpath_config_check(struct vxge_hw_vp_config *vp_config)
12458c2ecf20Sopenharmony_ci{
12468c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	if ((vp_config->min_bandwidth < VXGE_HW_VPATH_BANDWIDTH_MIN) ||
12498c2ecf20Sopenharmony_ci	    (vp_config->min_bandwidth >	VXGE_HW_VPATH_BANDWIDTH_MAX))
12508c2ecf20Sopenharmony_ci		return VXGE_HW_BADCFG_VPATH_MIN_BANDWIDTH;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	status = __vxge_hw_device_fifo_config_check(&vp_config->fifo);
12538c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
12548c2ecf20Sopenharmony_ci		return status;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	if ((vp_config->mtu != VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU) &&
12578c2ecf20Sopenharmony_ci		((vp_config->mtu < VXGE_HW_VPATH_MIN_INITIAL_MTU) ||
12588c2ecf20Sopenharmony_ci		(vp_config->mtu > VXGE_HW_VPATH_MAX_INITIAL_MTU)))
12598c2ecf20Sopenharmony_ci		return VXGE_HW_BADCFG_VPATH_MTU;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	if ((vp_config->rpa_strip_vlan_tag !=
12628c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT) &&
12638c2ecf20Sopenharmony_ci		(vp_config->rpa_strip_vlan_tag !=
12648c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE) &&
12658c2ecf20Sopenharmony_ci		(vp_config->rpa_strip_vlan_tag !=
12668c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_DISABLE))
12678c2ecf20Sopenharmony_ci		return VXGE_HW_BADCFG_VPATH_RPA_STRIP_VLAN_TAG;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci/*
12738c2ecf20Sopenharmony_ci * __vxge_hw_device_config_check - Check device configuration.
12748c2ecf20Sopenharmony_ci * Check the device configuration
12758c2ecf20Sopenharmony_ci */
12768c2ecf20Sopenharmony_cistatic enum vxge_hw_status
12778c2ecf20Sopenharmony_ci__vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
12788c2ecf20Sopenharmony_ci{
12798c2ecf20Sopenharmony_ci	u32 i;
12808c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	if ((new_config->intr_mode != VXGE_HW_INTR_MODE_IRQLINE) &&
12838c2ecf20Sopenharmony_ci	    (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX) &&
12848c2ecf20Sopenharmony_ci	    (new_config->intr_mode != VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) &&
12858c2ecf20Sopenharmony_ci	    (new_config->intr_mode != VXGE_HW_INTR_MODE_DEF))
12868c2ecf20Sopenharmony_ci		return VXGE_HW_BADCFG_INTR_MODE;
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	if ((new_config->rts_mac_en != VXGE_HW_RTS_MAC_DISABLE) &&
12898c2ecf20Sopenharmony_ci	    (new_config->rts_mac_en != VXGE_HW_RTS_MAC_ENABLE))
12908c2ecf20Sopenharmony_ci		return VXGE_HW_BADCFG_RTS_MAC_EN;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
12938c2ecf20Sopenharmony_ci		status = __vxge_hw_device_vpath_config_check(
12948c2ecf20Sopenharmony_ci				&new_config->vp_config[i]);
12958c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
12968c2ecf20Sopenharmony_ci			return status;
12978c2ecf20Sopenharmony_ci	}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
13008c2ecf20Sopenharmony_ci}
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci/*
13038c2ecf20Sopenharmony_ci * vxge_hw_device_initialize - Initialize Titan device.
13048c2ecf20Sopenharmony_ci * Initialize Titan device. Note that all the arguments of this public API
13058c2ecf20Sopenharmony_ci * are 'IN', including @hldev. Driver cooperates with
13068c2ecf20Sopenharmony_ci * OS to find new Titan device, locate its PCI and memory spaces.
13078c2ecf20Sopenharmony_ci *
13088c2ecf20Sopenharmony_ci * When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW
13098c2ecf20Sopenharmony_ci * to enable the latter to perform Titan hardware initialization.
13108c2ecf20Sopenharmony_ci */
13118c2ecf20Sopenharmony_cienum vxge_hw_status
13128c2ecf20Sopenharmony_civxge_hw_device_initialize(
13138c2ecf20Sopenharmony_ci	struct __vxge_hw_device **devh,
13148c2ecf20Sopenharmony_ci	struct vxge_hw_device_attr *attr,
13158c2ecf20Sopenharmony_ci	struct vxge_hw_device_config *device_config)
13168c2ecf20Sopenharmony_ci{
13178c2ecf20Sopenharmony_ci	u32 i;
13188c2ecf20Sopenharmony_ci	u32 nblocks = 0;
13198c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev = NULL;
13208c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	status = __vxge_hw_device_config_check(device_config);
13238c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
13248c2ecf20Sopenharmony_ci		goto exit;
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	hldev = vzalloc(sizeof(struct __vxge_hw_device));
13278c2ecf20Sopenharmony_ci	if (hldev == NULL) {
13288c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
13298c2ecf20Sopenharmony_ci		goto exit;
13308c2ecf20Sopenharmony_ci	}
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	hldev->magic = VXGE_HW_DEVICE_MAGIC;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_ALL);
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	/* apply config */
13378c2ecf20Sopenharmony_ci	memcpy(&hldev->config, device_config,
13388c2ecf20Sopenharmony_ci		sizeof(struct vxge_hw_device_config));
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	hldev->bar0 = attr->bar0;
13418c2ecf20Sopenharmony_ci	hldev->pdev = attr->pdev;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	hldev->uld_callbacks = attr->uld_callbacks;
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	__vxge_hw_device_pci_e_init(hldev);
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	status = __vxge_hw_device_reg_addr_get(hldev);
13488c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
13498c2ecf20Sopenharmony_ci		vfree(hldev);
13508c2ecf20Sopenharmony_ci		goto exit;
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	__vxge_hw_device_host_info_get(hldev);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	/* Incrementing for stats blocks */
13568c2ecf20Sopenharmony_ci	nblocks++;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
13598c2ecf20Sopenharmony_ci		if (!(hldev->vpath_assignments & vxge_mBIT(i)))
13608c2ecf20Sopenharmony_ci			continue;
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci		if (device_config->vp_config[i].ring.enable ==
13638c2ecf20Sopenharmony_ci			VXGE_HW_RING_ENABLE)
13648c2ecf20Sopenharmony_ci			nblocks += device_config->vp_config[i].ring.ring_blocks;
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci		if (device_config->vp_config[i].fifo.enable ==
13678c2ecf20Sopenharmony_ci			VXGE_HW_FIFO_ENABLE)
13688c2ecf20Sopenharmony_ci			nblocks += device_config->vp_config[i].fifo.fifo_blocks;
13698c2ecf20Sopenharmony_ci		nblocks++;
13708c2ecf20Sopenharmony_ci	}
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	if (__vxge_hw_blockpool_create(hldev,
13738c2ecf20Sopenharmony_ci		&hldev->block_pool,
13748c2ecf20Sopenharmony_ci		device_config->dma_blockpool_initial + nblocks,
13758c2ecf20Sopenharmony_ci		device_config->dma_blockpool_max + nblocks) != VXGE_HW_OK) {
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci		vxge_hw_device_terminate(hldev);
13788c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
13798c2ecf20Sopenharmony_ci		goto exit;
13808c2ecf20Sopenharmony_ci	}
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci	status = __vxge_hw_device_initialize(hldev);
13838c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
13848c2ecf20Sopenharmony_ci		vxge_hw_device_terminate(hldev);
13858c2ecf20Sopenharmony_ci		goto exit;
13868c2ecf20Sopenharmony_ci	}
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	*devh = hldev;
13898c2ecf20Sopenharmony_ciexit:
13908c2ecf20Sopenharmony_ci	return status;
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci/*
13948c2ecf20Sopenharmony_ci * vxge_hw_device_terminate - Terminate Titan device.
13958c2ecf20Sopenharmony_ci * Terminate HW device.
13968c2ecf20Sopenharmony_ci */
13978c2ecf20Sopenharmony_civoid
13988c2ecf20Sopenharmony_civxge_hw_device_terminate(struct __vxge_hw_device *hldev)
13998c2ecf20Sopenharmony_ci{
14008c2ecf20Sopenharmony_ci	vxge_assert(hldev->magic == VXGE_HW_DEVICE_MAGIC);
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	hldev->magic = VXGE_HW_DEVICE_DEAD;
14038c2ecf20Sopenharmony_ci	__vxge_hw_blockpool_destroy(&hldev->block_pool);
14048c2ecf20Sopenharmony_ci	vfree(hldev);
14058c2ecf20Sopenharmony_ci}
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci/*
14088c2ecf20Sopenharmony_ci * __vxge_hw_vpath_stats_access - Get the statistics from the given location
14098c2ecf20Sopenharmony_ci *                           and offset and perform an operation
14108c2ecf20Sopenharmony_ci */
14118c2ecf20Sopenharmony_cistatic enum vxge_hw_status
14128c2ecf20Sopenharmony_ci__vxge_hw_vpath_stats_access(struct __vxge_hw_virtualpath *vpath,
14138c2ecf20Sopenharmony_ci			     u32 operation, u32 offset, u64 *stat)
14148c2ecf20Sopenharmony_ci{
14158c2ecf20Sopenharmony_ci	u64 val64;
14168c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
14178c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
14208c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
14218c2ecf20Sopenharmony_ci		goto vpath_stats_access_exit;
14228c2ecf20Sopenharmony_ci	}
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	val64 =  VXGE_HW_XMAC_STATS_ACCESS_CMD_OP(operation) |
14278c2ecf20Sopenharmony_ci		 VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE |
14288c2ecf20Sopenharmony_ci		 VXGE_HW_XMAC_STATS_ACCESS_CMD_OFFSET_SEL(offset);
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	status = __vxge_hw_pio_mem_write64(val64,
14318c2ecf20Sopenharmony_ci				&vp_reg->xmac_stats_access_cmd,
14328c2ecf20Sopenharmony_ci				VXGE_HW_XMAC_STATS_ACCESS_CMD_STROBE,
14338c2ecf20Sopenharmony_ci				vpath->hldev->config.device_poll_millis);
14348c2ecf20Sopenharmony_ci	if ((status == VXGE_HW_OK) && (operation == VXGE_HW_STATS_OP_READ))
14358c2ecf20Sopenharmony_ci		*stat = readq(&vp_reg->xmac_stats_access_data);
14368c2ecf20Sopenharmony_ci	else
14378c2ecf20Sopenharmony_ci		*stat = 0;
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_civpath_stats_access_exit:
14408c2ecf20Sopenharmony_ci	return status;
14418c2ecf20Sopenharmony_ci}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci/*
14448c2ecf20Sopenharmony_ci * __vxge_hw_vpath_xmac_tx_stats_get - Get the TX Statistics of a vpath
14458c2ecf20Sopenharmony_ci */
14468c2ecf20Sopenharmony_cistatic enum vxge_hw_status
14478c2ecf20Sopenharmony_ci__vxge_hw_vpath_xmac_tx_stats_get(struct __vxge_hw_virtualpath *vpath,
14488c2ecf20Sopenharmony_ci			struct vxge_hw_xmac_vpath_tx_stats *vpath_tx_stats)
14498c2ecf20Sopenharmony_ci{
14508c2ecf20Sopenharmony_ci	u64 *val64;
14518c2ecf20Sopenharmony_ci	int i;
14528c2ecf20Sopenharmony_ci	u32 offset = VXGE_HW_STATS_VPATH_TX_OFFSET;
14538c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	val64 = (u64 *)vpath_tx_stats;
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
14588c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
14598c2ecf20Sopenharmony_ci		goto exit;
14608c2ecf20Sopenharmony_ci	}
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_tx_stats) / 8; i++) {
14638c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_stats_access(vpath,
14648c2ecf20Sopenharmony_ci					VXGE_HW_STATS_OP_READ,
14658c2ecf20Sopenharmony_ci					offset, val64);
14668c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
14678c2ecf20Sopenharmony_ci			goto exit;
14688c2ecf20Sopenharmony_ci		offset++;
14698c2ecf20Sopenharmony_ci		val64++;
14708c2ecf20Sopenharmony_ci	}
14718c2ecf20Sopenharmony_ciexit:
14728c2ecf20Sopenharmony_ci	return status;
14738c2ecf20Sopenharmony_ci}
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci/*
14768c2ecf20Sopenharmony_ci * __vxge_hw_vpath_xmac_rx_stats_get - Get the RX Statistics of a vpath
14778c2ecf20Sopenharmony_ci */
14788c2ecf20Sopenharmony_cistatic enum vxge_hw_status
14798c2ecf20Sopenharmony_ci__vxge_hw_vpath_xmac_rx_stats_get(struct __vxge_hw_virtualpath *vpath,
14808c2ecf20Sopenharmony_ci			struct vxge_hw_xmac_vpath_rx_stats *vpath_rx_stats)
14818c2ecf20Sopenharmony_ci{
14828c2ecf20Sopenharmony_ci	u64 *val64;
14838c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
14848c2ecf20Sopenharmony_ci	int i;
14858c2ecf20Sopenharmony_ci	u32 offset = VXGE_HW_STATS_VPATH_RX_OFFSET;
14868c2ecf20Sopenharmony_ci	val64 = (u64 *) vpath_rx_stats;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
14898c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
14908c2ecf20Sopenharmony_ci		goto exit;
14918c2ecf20Sopenharmony_ci	}
14928c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(struct vxge_hw_xmac_vpath_rx_stats) / 8; i++) {
14938c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_stats_access(vpath,
14948c2ecf20Sopenharmony_ci					VXGE_HW_STATS_OP_READ,
14958c2ecf20Sopenharmony_ci					offset >> 3, val64);
14968c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
14978c2ecf20Sopenharmony_ci			goto exit;
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci		offset += 8;
15008c2ecf20Sopenharmony_ci		val64++;
15018c2ecf20Sopenharmony_ci	}
15028c2ecf20Sopenharmony_ciexit:
15038c2ecf20Sopenharmony_ci	return status;
15048c2ecf20Sopenharmony_ci}
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci/*
15078c2ecf20Sopenharmony_ci * __vxge_hw_vpath_stats_get - Get the vpath hw statistics.
15088c2ecf20Sopenharmony_ci */
15098c2ecf20Sopenharmony_cistatic enum vxge_hw_status
15108c2ecf20Sopenharmony_ci__vxge_hw_vpath_stats_get(struct __vxge_hw_virtualpath *vpath,
15118c2ecf20Sopenharmony_ci			  struct vxge_hw_vpath_stats_hw_info *hw_stats)
15128c2ecf20Sopenharmony_ci{
15138c2ecf20Sopenharmony_ci	u64 val64;
15148c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
15158c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
15188c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
15198c2ecf20Sopenharmony_ci		goto exit;
15208c2ecf20Sopenharmony_ci	}
15218c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats0);
15248c2ecf20Sopenharmony_ci	hw_stats->ini_num_mwr_sent =
15258c2ecf20Sopenharmony_ci		(u32)VXGE_HW_VPATH_DEBUG_STATS0_GET_INI_NUM_MWR_SENT(val64);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats1);
15288c2ecf20Sopenharmony_ci	hw_stats->ini_num_mrd_sent =
15298c2ecf20Sopenharmony_ci		(u32)VXGE_HW_VPATH_DEBUG_STATS1_GET_INI_NUM_MRD_SENT(val64);
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats2);
15328c2ecf20Sopenharmony_ci	hw_stats->ini_num_cpl_rcvd =
15338c2ecf20Sopenharmony_ci		(u32)VXGE_HW_VPATH_DEBUG_STATS2_GET_INI_NUM_CPL_RCVD(val64);
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats3);
15368c2ecf20Sopenharmony_ci	hw_stats->ini_num_mwr_byte_sent =
15378c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_DEBUG_STATS3_GET_INI_NUM_MWR_BYTE_SENT(val64);
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats4);
15408c2ecf20Sopenharmony_ci	hw_stats->ini_num_cpl_byte_rcvd =
15418c2ecf20Sopenharmony_ci		VXGE_HW_VPATH_DEBUG_STATS4_GET_INI_NUM_CPL_BYTE_RCVD(val64);
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats5);
15448c2ecf20Sopenharmony_ci	hw_stats->wrcrdtarb_xoff =
15458c2ecf20Sopenharmony_ci		(u32)VXGE_HW_VPATH_DEBUG_STATS5_GET_WRCRDTARB_XOFF(val64);
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_debug_stats6);
15488c2ecf20Sopenharmony_ci	hw_stats->rdcrdtarb_xoff =
15498c2ecf20Sopenharmony_ci		(u32)VXGE_HW_VPATH_DEBUG_STATS6_GET_RDCRDTARB_XOFF(val64);
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_genstats_count01);
15528c2ecf20Sopenharmony_ci	hw_stats->vpath_genstats_count0 =
15538c2ecf20Sopenharmony_ci	(u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT0(
15548c2ecf20Sopenharmony_ci		val64);
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_genstats_count01);
15578c2ecf20Sopenharmony_ci	hw_stats->vpath_genstats_count1 =
15588c2ecf20Sopenharmony_ci	(u32)VXGE_HW_VPATH_GENSTATS_COUNT01_GET_PPIF_VPATH_GENSTATS_COUNT1(
15598c2ecf20Sopenharmony_ci		val64);
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_genstats_count23);
15628c2ecf20Sopenharmony_ci	hw_stats->vpath_genstats_count2 =
15638c2ecf20Sopenharmony_ci	(u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT2(
15648c2ecf20Sopenharmony_ci		val64);
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_genstats_count01);
15678c2ecf20Sopenharmony_ci	hw_stats->vpath_genstats_count3 =
15688c2ecf20Sopenharmony_ci	(u32)VXGE_HW_VPATH_GENSTATS_COUNT23_GET_PPIF_VPATH_GENSTATS_COUNT3(
15698c2ecf20Sopenharmony_ci		val64);
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_genstats_count4);
15728c2ecf20Sopenharmony_ci	hw_stats->vpath_genstats_count4 =
15738c2ecf20Sopenharmony_ci	(u32)VXGE_HW_VPATH_GENSTATS_COUNT4_GET_PPIF_VPATH_GENSTATS_COUNT4(
15748c2ecf20Sopenharmony_ci		val64);
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->vpath_genstats_count5);
15778c2ecf20Sopenharmony_ci	hw_stats->vpath_genstats_count5 =
15788c2ecf20Sopenharmony_ci	(u32)VXGE_HW_VPATH_GENSTATS_COUNT5_GET_PPIF_VPATH_GENSTATS_COUNT5(
15798c2ecf20Sopenharmony_ci		val64);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_xmac_tx_stats_get(vpath, &hw_stats->tx_stats);
15828c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
15838c2ecf20Sopenharmony_ci		goto exit;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_xmac_rx_stats_get(vpath, &hw_stats->rx_stats);
15868c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
15878c2ecf20Sopenharmony_ci		goto exit;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	VXGE_HW_VPATH_STATS_PIO_READ(
15908c2ecf20Sopenharmony_ci		VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM0_OFFSET);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	hw_stats->prog_event_vnum0 =
15938c2ecf20Sopenharmony_ci			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM0(val64);
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	hw_stats->prog_event_vnum1 =
15968c2ecf20Sopenharmony_ci			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM1(val64);
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	VXGE_HW_VPATH_STATS_PIO_READ(
15998c2ecf20Sopenharmony_ci		VXGE_HW_STATS_VPATH_PROG_EVENT_VNUM2_OFFSET);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	hw_stats->prog_event_vnum2 =
16028c2ecf20Sopenharmony_ci			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM2(val64);
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	hw_stats->prog_event_vnum3 =
16058c2ecf20Sopenharmony_ci			(u32)VXGE_HW_STATS_GET_VPATH_PROG_EVENT_VNUM3(val64);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rx_multi_cast_stats);
16088c2ecf20Sopenharmony_ci	hw_stats->rx_multi_cast_frame_discard =
16098c2ecf20Sopenharmony_ci		(u16)VXGE_HW_RX_MULTI_CAST_STATS_GET_FRAME_DISCARD(val64);
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rx_frm_transferred);
16128c2ecf20Sopenharmony_ci	hw_stats->rx_frm_transferred =
16138c2ecf20Sopenharmony_ci		(u32)VXGE_HW_RX_FRM_TRANSFERRED_GET_RX_FRM_TRANSFERRED(val64);
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rxd_returned);
16168c2ecf20Sopenharmony_ci	hw_stats->rxd_returned =
16178c2ecf20Sopenharmony_ci		(u16)VXGE_HW_RXD_RETURNED_GET_RXD_RETURNED(val64);
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->dbg_stats_rx_mpa);
16208c2ecf20Sopenharmony_ci	hw_stats->rx_mpa_len_fail_frms =
16218c2ecf20Sopenharmony_ci		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_LEN_FAIL_FRMS(val64);
16228c2ecf20Sopenharmony_ci	hw_stats->rx_mpa_mrk_fail_frms =
16238c2ecf20Sopenharmony_ci		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_MRK_FAIL_FRMS(val64);
16248c2ecf20Sopenharmony_ci	hw_stats->rx_mpa_crc_fail_frms =
16258c2ecf20Sopenharmony_ci		(u16)VXGE_HW_DBG_STATS_GET_RX_MPA_CRC_FAIL_FRMS(val64);
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->dbg_stats_rx_fau);
16288c2ecf20Sopenharmony_ci	hw_stats->rx_permitted_frms =
16298c2ecf20Sopenharmony_ci		(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_PERMITTED_FRMS(val64);
16308c2ecf20Sopenharmony_ci	hw_stats->rx_vp_reset_discarded_frms =
16318c2ecf20Sopenharmony_ci	(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_VP_RESET_DISCARDED_FRMS(val64);
16328c2ecf20Sopenharmony_ci	hw_stats->rx_wol_frms =
16338c2ecf20Sopenharmony_ci		(u16)VXGE_HW_DBG_STATS_GET_RX_FAU_RX_WOL_FRMS(val64);
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->tx_vp_reset_discarded_frms);
16368c2ecf20Sopenharmony_ci	hw_stats->tx_vp_reset_discarded_frms =
16378c2ecf20Sopenharmony_ci	(u16)VXGE_HW_TX_VP_RESET_DISCARDED_FRMS_GET_TX_VP_RESET_DISCARDED_FRMS(
16388c2ecf20Sopenharmony_ci		val64);
16398c2ecf20Sopenharmony_ciexit:
16408c2ecf20Sopenharmony_ci	return status;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci/*
16448c2ecf20Sopenharmony_ci * vxge_hw_device_stats_get - Get the device hw statistics.
16458c2ecf20Sopenharmony_ci * Returns the vpath h/w stats for the device.
16468c2ecf20Sopenharmony_ci */
16478c2ecf20Sopenharmony_cienum vxge_hw_status
16488c2ecf20Sopenharmony_civxge_hw_device_stats_get(struct __vxge_hw_device *hldev,
16498c2ecf20Sopenharmony_ci			struct vxge_hw_device_stats_hw_info *hw_stats)
16508c2ecf20Sopenharmony_ci{
16518c2ecf20Sopenharmony_ci	u32 i;
16528c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
16558c2ecf20Sopenharmony_ci		if (!(hldev->vpaths_deployed & vxge_mBIT(i)) ||
16568c2ecf20Sopenharmony_ci			(hldev->virtual_paths[i].vp_open ==
16578c2ecf20Sopenharmony_ci				VXGE_HW_VP_NOT_OPEN))
16588c2ecf20Sopenharmony_ci			continue;
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci		memcpy(hldev->virtual_paths[i].hw_stats_sav,
16618c2ecf20Sopenharmony_ci				hldev->virtual_paths[i].hw_stats,
16628c2ecf20Sopenharmony_ci				sizeof(struct vxge_hw_vpath_stats_hw_info));
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_stats_get(
16658c2ecf20Sopenharmony_ci			&hldev->virtual_paths[i],
16668c2ecf20Sopenharmony_ci			hldev->virtual_paths[i].hw_stats);
16678c2ecf20Sopenharmony_ci	}
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	memcpy(hw_stats, &hldev->stats.hw_dev_info_stats,
16708c2ecf20Sopenharmony_ci			sizeof(struct vxge_hw_device_stats_hw_info));
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	return status;
16738c2ecf20Sopenharmony_ci}
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci/*
16768c2ecf20Sopenharmony_ci * vxge_hw_driver_stats_get - Get the device sw statistics.
16778c2ecf20Sopenharmony_ci * Returns the vpath s/w stats for the device.
16788c2ecf20Sopenharmony_ci */
16798c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_driver_stats_get(
16808c2ecf20Sopenharmony_ci			struct __vxge_hw_device *hldev,
16818c2ecf20Sopenharmony_ci			struct vxge_hw_device_stats_sw_info *sw_stats)
16828c2ecf20Sopenharmony_ci{
16838c2ecf20Sopenharmony_ci	memcpy(sw_stats, &hldev->stats.sw_dev_info_stats,
16848c2ecf20Sopenharmony_ci		sizeof(struct vxge_hw_device_stats_sw_info));
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
16878c2ecf20Sopenharmony_ci}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci/*
16908c2ecf20Sopenharmony_ci * vxge_hw_mrpcim_stats_access - Access the statistics from the given location
16918c2ecf20Sopenharmony_ci *                           and offset and perform an operation
16928c2ecf20Sopenharmony_ci * Get the statistics from the given location and offset.
16938c2ecf20Sopenharmony_ci */
16948c2ecf20Sopenharmony_cienum vxge_hw_status
16958c2ecf20Sopenharmony_civxge_hw_mrpcim_stats_access(struct __vxge_hw_device *hldev,
16968c2ecf20Sopenharmony_ci			    u32 operation, u32 location, u32 offset, u64 *stat)
16978c2ecf20Sopenharmony_ci{
16988c2ecf20Sopenharmony_ci	u64 val64;
16998c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	status = __vxge_hw_device_is_privilaged(hldev->host_type,
17028c2ecf20Sopenharmony_ci			hldev->func_id);
17038c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
17048c2ecf20Sopenharmony_ci		goto exit;
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	val64 = VXGE_HW_XMAC_STATS_SYS_CMD_OP(operation) |
17078c2ecf20Sopenharmony_ci		VXGE_HW_XMAC_STATS_SYS_CMD_STROBE |
17088c2ecf20Sopenharmony_ci		VXGE_HW_XMAC_STATS_SYS_CMD_LOC_SEL(location) |
17098c2ecf20Sopenharmony_ci		VXGE_HW_XMAC_STATS_SYS_CMD_OFFSET_SEL(offset);
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	status = __vxge_hw_pio_mem_write64(val64,
17128c2ecf20Sopenharmony_ci				&hldev->mrpcim_reg->xmac_stats_sys_cmd,
17138c2ecf20Sopenharmony_ci				VXGE_HW_XMAC_STATS_SYS_CMD_STROBE,
17148c2ecf20Sopenharmony_ci				hldev->config.device_poll_millis);
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci	if ((status == VXGE_HW_OK) && (operation == VXGE_HW_STATS_OP_READ))
17178c2ecf20Sopenharmony_ci		*stat = readq(&hldev->mrpcim_reg->xmac_stats_sys_data);
17188c2ecf20Sopenharmony_ci	else
17198c2ecf20Sopenharmony_ci		*stat = 0;
17208c2ecf20Sopenharmony_ciexit:
17218c2ecf20Sopenharmony_ci	return status;
17228c2ecf20Sopenharmony_ci}
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci/*
17258c2ecf20Sopenharmony_ci * vxge_hw_device_xmac_aggr_stats_get - Get the Statistics on aggregate port
17268c2ecf20Sopenharmony_ci * Get the Statistics on aggregate port
17278c2ecf20Sopenharmony_ci */
17288c2ecf20Sopenharmony_cistatic enum vxge_hw_status
17298c2ecf20Sopenharmony_civxge_hw_device_xmac_aggr_stats_get(struct __vxge_hw_device *hldev, u32 port,
17308c2ecf20Sopenharmony_ci				   struct vxge_hw_xmac_aggr_stats *aggr_stats)
17318c2ecf20Sopenharmony_ci{
17328c2ecf20Sopenharmony_ci	u64 *val64;
17338c2ecf20Sopenharmony_ci	int i;
17348c2ecf20Sopenharmony_ci	u32 offset = VXGE_HW_STATS_AGGRn_OFFSET;
17358c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	val64 = (u64 *)aggr_stats;
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	status = __vxge_hw_device_is_privilaged(hldev->host_type,
17408c2ecf20Sopenharmony_ci			hldev->func_id);
17418c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
17428c2ecf20Sopenharmony_ci		goto exit;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(struct vxge_hw_xmac_aggr_stats) / 8; i++) {
17458c2ecf20Sopenharmony_ci		status = vxge_hw_mrpcim_stats_access(hldev,
17468c2ecf20Sopenharmony_ci					VXGE_HW_STATS_OP_READ,
17478c2ecf20Sopenharmony_ci					VXGE_HW_STATS_LOC_AGGR,
17488c2ecf20Sopenharmony_ci					((offset + (104 * port)) >> 3), val64);
17498c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
17508c2ecf20Sopenharmony_ci			goto exit;
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci		offset += 8;
17538c2ecf20Sopenharmony_ci		val64++;
17548c2ecf20Sopenharmony_ci	}
17558c2ecf20Sopenharmony_ciexit:
17568c2ecf20Sopenharmony_ci	return status;
17578c2ecf20Sopenharmony_ci}
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci/*
17608c2ecf20Sopenharmony_ci * vxge_hw_device_xmac_port_stats_get - Get the Statistics on a port
17618c2ecf20Sopenharmony_ci * Get the Statistics on port
17628c2ecf20Sopenharmony_ci */
17638c2ecf20Sopenharmony_cistatic enum vxge_hw_status
17648c2ecf20Sopenharmony_civxge_hw_device_xmac_port_stats_get(struct __vxge_hw_device *hldev, u32 port,
17658c2ecf20Sopenharmony_ci				   struct vxge_hw_xmac_port_stats *port_stats)
17668c2ecf20Sopenharmony_ci{
17678c2ecf20Sopenharmony_ci	u64 *val64;
17688c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
17698c2ecf20Sopenharmony_ci	int i;
17708c2ecf20Sopenharmony_ci	u32 offset = 0x0;
17718c2ecf20Sopenharmony_ci	val64 = (u64 *) port_stats;
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	status = __vxge_hw_device_is_privilaged(hldev->host_type,
17748c2ecf20Sopenharmony_ci			hldev->func_id);
17758c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
17768c2ecf20Sopenharmony_ci		goto exit;
17778c2ecf20Sopenharmony_ci
17788c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(struct vxge_hw_xmac_port_stats) / 8; i++) {
17798c2ecf20Sopenharmony_ci		status = vxge_hw_mrpcim_stats_access(hldev,
17808c2ecf20Sopenharmony_ci					VXGE_HW_STATS_OP_READ,
17818c2ecf20Sopenharmony_ci					VXGE_HW_STATS_LOC_AGGR,
17828c2ecf20Sopenharmony_ci					((offset + (608 * port)) >> 3), val64);
17838c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
17848c2ecf20Sopenharmony_ci			goto exit;
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci		offset += 8;
17878c2ecf20Sopenharmony_ci		val64++;
17888c2ecf20Sopenharmony_ci	}
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ciexit:
17918c2ecf20Sopenharmony_ci	return status;
17928c2ecf20Sopenharmony_ci}
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci/*
17958c2ecf20Sopenharmony_ci * vxge_hw_device_xmac_stats_get - Get the XMAC Statistics
17968c2ecf20Sopenharmony_ci * Get the XMAC Statistics
17978c2ecf20Sopenharmony_ci */
17988c2ecf20Sopenharmony_cienum vxge_hw_status
17998c2ecf20Sopenharmony_civxge_hw_device_xmac_stats_get(struct __vxge_hw_device *hldev,
18008c2ecf20Sopenharmony_ci			      struct vxge_hw_xmac_stats *xmac_stats)
18018c2ecf20Sopenharmony_ci{
18028c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
18038c2ecf20Sopenharmony_ci	u32 i;
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	status = vxge_hw_device_xmac_aggr_stats_get(hldev,
18068c2ecf20Sopenharmony_ci					0, &xmac_stats->aggr_stats[0]);
18078c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
18088c2ecf20Sopenharmony_ci		goto exit;
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	status = vxge_hw_device_xmac_aggr_stats_get(hldev,
18118c2ecf20Sopenharmony_ci				1, &xmac_stats->aggr_stats[1]);
18128c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
18138c2ecf20Sopenharmony_ci		goto exit;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	for (i = 0; i <= VXGE_HW_MAC_MAX_MAC_PORT_ID; i++) {
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci		status = vxge_hw_device_xmac_port_stats_get(hldev,
18188c2ecf20Sopenharmony_ci					i, &xmac_stats->port_stats[i]);
18198c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
18208c2ecf20Sopenharmony_ci			goto exit;
18218c2ecf20Sopenharmony_ci	}
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
18268c2ecf20Sopenharmony_ci			continue;
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_xmac_tx_stats_get(
18298c2ecf20Sopenharmony_ci					&hldev->virtual_paths[i],
18308c2ecf20Sopenharmony_ci					&xmac_stats->vpath_tx_stats[i]);
18318c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
18328c2ecf20Sopenharmony_ci			goto exit;
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci		status = __vxge_hw_vpath_xmac_rx_stats_get(
18358c2ecf20Sopenharmony_ci					&hldev->virtual_paths[i],
18368c2ecf20Sopenharmony_ci					&xmac_stats->vpath_rx_stats[i]);
18378c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
18388c2ecf20Sopenharmony_ci			goto exit;
18398c2ecf20Sopenharmony_ci	}
18408c2ecf20Sopenharmony_ciexit:
18418c2ecf20Sopenharmony_ci	return status;
18428c2ecf20Sopenharmony_ci}
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci/*
18458c2ecf20Sopenharmony_ci * vxge_hw_device_debug_set - Set the debug module, level and timestamp
18468c2ecf20Sopenharmony_ci * This routine is used to dynamically change the debug output
18478c2ecf20Sopenharmony_ci */
18488c2ecf20Sopenharmony_civoid vxge_hw_device_debug_set(struct __vxge_hw_device *hldev,
18498c2ecf20Sopenharmony_ci			      enum vxge_debug_level level, u32 mask)
18508c2ecf20Sopenharmony_ci{
18518c2ecf20Sopenharmony_ci	if (hldev == NULL)
18528c2ecf20Sopenharmony_ci		return;
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci#if defined(VXGE_DEBUG_TRACE_MASK) || \
18558c2ecf20Sopenharmony_ci	defined(VXGE_DEBUG_ERR_MASK)
18568c2ecf20Sopenharmony_ci	hldev->debug_module_mask = mask;
18578c2ecf20Sopenharmony_ci	hldev->debug_level = level;
18588c2ecf20Sopenharmony_ci#endif
18598c2ecf20Sopenharmony_ci
18608c2ecf20Sopenharmony_ci#if defined(VXGE_DEBUG_ERR_MASK)
18618c2ecf20Sopenharmony_ci	hldev->level_err = level & VXGE_ERR;
18628c2ecf20Sopenharmony_ci#endif
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci#if defined(VXGE_DEBUG_TRACE_MASK)
18658c2ecf20Sopenharmony_ci	hldev->level_trace = level & VXGE_TRACE;
18668c2ecf20Sopenharmony_ci#endif
18678c2ecf20Sopenharmony_ci}
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci/*
18708c2ecf20Sopenharmony_ci * vxge_hw_device_error_level_get - Get the error level
18718c2ecf20Sopenharmony_ci * This routine returns the current error level set
18728c2ecf20Sopenharmony_ci */
18738c2ecf20Sopenharmony_ciu32 vxge_hw_device_error_level_get(struct __vxge_hw_device *hldev)
18748c2ecf20Sopenharmony_ci{
18758c2ecf20Sopenharmony_ci#if defined(VXGE_DEBUG_ERR_MASK)
18768c2ecf20Sopenharmony_ci	if (hldev == NULL)
18778c2ecf20Sopenharmony_ci		return VXGE_ERR;
18788c2ecf20Sopenharmony_ci	else
18798c2ecf20Sopenharmony_ci		return hldev->level_err;
18808c2ecf20Sopenharmony_ci#else
18818c2ecf20Sopenharmony_ci	return 0;
18828c2ecf20Sopenharmony_ci#endif
18838c2ecf20Sopenharmony_ci}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci/*
18868c2ecf20Sopenharmony_ci * vxge_hw_device_trace_level_get - Get the trace level
18878c2ecf20Sopenharmony_ci * This routine returns the current trace level set
18888c2ecf20Sopenharmony_ci */
18898c2ecf20Sopenharmony_ciu32 vxge_hw_device_trace_level_get(struct __vxge_hw_device *hldev)
18908c2ecf20Sopenharmony_ci{
18918c2ecf20Sopenharmony_ci#if defined(VXGE_DEBUG_TRACE_MASK)
18928c2ecf20Sopenharmony_ci	if (hldev == NULL)
18938c2ecf20Sopenharmony_ci		return VXGE_TRACE;
18948c2ecf20Sopenharmony_ci	else
18958c2ecf20Sopenharmony_ci		return hldev->level_trace;
18968c2ecf20Sopenharmony_ci#else
18978c2ecf20Sopenharmony_ci	return 0;
18988c2ecf20Sopenharmony_ci#endif
18998c2ecf20Sopenharmony_ci}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci/*
19028c2ecf20Sopenharmony_ci * vxge_hw_getpause_data -Pause frame frame generation and reception.
19038c2ecf20Sopenharmony_ci * Returns the Pause frame generation and reception capability of the NIC.
19048c2ecf20Sopenharmony_ci */
19058c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_device_getpause_data(struct __vxge_hw_device *hldev,
19068c2ecf20Sopenharmony_ci						 u32 port, u32 *tx, u32 *rx)
19078c2ecf20Sopenharmony_ci{
19088c2ecf20Sopenharmony_ci	u64 val64;
19098c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
19128c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_DEVICE;
19138c2ecf20Sopenharmony_ci		goto exit;
19148c2ecf20Sopenharmony_ci	}
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ci	if (port > VXGE_HW_MAC_MAX_MAC_PORT_ID) {
19178c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_PORT;
19188c2ecf20Sopenharmony_ci		goto exit;
19198c2ecf20Sopenharmony_ci	}
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci	if (!(hldev->access_rights & VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) {
19228c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_PRIVILEGED_OPERATION;
19238c2ecf20Sopenharmony_ci		goto exit;
19248c2ecf20Sopenharmony_ci	}
19258c2ecf20Sopenharmony_ci
19268c2ecf20Sopenharmony_ci	val64 = readq(&hldev->mrpcim_reg->rxmac_pause_cfg_port[port]);
19278c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN)
19288c2ecf20Sopenharmony_ci		*tx = 1;
19298c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN)
19308c2ecf20Sopenharmony_ci		*rx = 1;
19318c2ecf20Sopenharmony_ciexit:
19328c2ecf20Sopenharmony_ci	return status;
19338c2ecf20Sopenharmony_ci}
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci/*
19368c2ecf20Sopenharmony_ci * vxge_hw_device_setpause_data -  set/reset pause frame generation.
19378c2ecf20Sopenharmony_ci * It can be used to set or reset Pause frame generation or reception
19388c2ecf20Sopenharmony_ci * support of the NIC.
19398c2ecf20Sopenharmony_ci */
19408c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev,
19418c2ecf20Sopenharmony_ci						 u32 port, u32 tx, u32 rx)
19428c2ecf20Sopenharmony_ci{
19438c2ecf20Sopenharmony_ci	u64 val64;
19448c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci	if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
19478c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_DEVICE;
19488c2ecf20Sopenharmony_ci		goto exit;
19498c2ecf20Sopenharmony_ci	}
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	if (port > VXGE_HW_MAC_MAX_MAC_PORT_ID) {
19528c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_PORT;
19538c2ecf20Sopenharmony_ci		goto exit;
19548c2ecf20Sopenharmony_ci	}
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci	status = __vxge_hw_device_is_privilaged(hldev->host_type,
19578c2ecf20Sopenharmony_ci			hldev->func_id);
19588c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
19598c2ecf20Sopenharmony_ci		goto exit;
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	val64 = readq(&hldev->mrpcim_reg->rxmac_pause_cfg_port[port]);
19628c2ecf20Sopenharmony_ci	if (tx)
19638c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN;
19648c2ecf20Sopenharmony_ci	else
19658c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_RXMAC_PAUSE_CFG_PORT_GEN_EN;
19668c2ecf20Sopenharmony_ci	if (rx)
19678c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN;
19688c2ecf20Sopenharmony_ci	else
19698c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_RXMAC_PAUSE_CFG_PORT_RCV_EN;
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci	writeq(val64, &hldev->mrpcim_reg->rxmac_pause_cfg_port[port]);
19728c2ecf20Sopenharmony_ciexit:
19738c2ecf20Sopenharmony_ci	return status;
19748c2ecf20Sopenharmony_ci}
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ciu16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev)
19778c2ecf20Sopenharmony_ci{
19788c2ecf20Sopenharmony_ci	struct pci_dev *dev = hldev->pdev;
19798c2ecf20Sopenharmony_ci	u16 lnk;
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnk);
19828c2ecf20Sopenharmony_ci	return (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
19838c2ecf20Sopenharmony_ci}
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci/*
19868c2ecf20Sopenharmony_ci * __vxge_hw_ring_block_memblock_idx - Return the memblock index
19878c2ecf20Sopenharmony_ci * This function returns the index of memory block
19888c2ecf20Sopenharmony_ci */
19898c2ecf20Sopenharmony_cistatic inline u32
19908c2ecf20Sopenharmony_ci__vxge_hw_ring_block_memblock_idx(u8 *block)
19918c2ecf20Sopenharmony_ci{
19928c2ecf20Sopenharmony_ci	return (u32)*((u64 *)(block + VXGE_HW_RING_MEMBLOCK_IDX_OFFSET));
19938c2ecf20Sopenharmony_ci}
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci/*
19968c2ecf20Sopenharmony_ci * __vxge_hw_ring_block_memblock_idx_set - Sets the memblock index
19978c2ecf20Sopenharmony_ci * This function sets index to a memory block
19988c2ecf20Sopenharmony_ci */
19998c2ecf20Sopenharmony_cistatic inline void
20008c2ecf20Sopenharmony_ci__vxge_hw_ring_block_memblock_idx_set(u8 *block, u32 memblock_idx)
20018c2ecf20Sopenharmony_ci{
20028c2ecf20Sopenharmony_ci	*((u64 *)(block + VXGE_HW_RING_MEMBLOCK_IDX_OFFSET)) = memblock_idx;
20038c2ecf20Sopenharmony_ci}
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_ci/*
20068c2ecf20Sopenharmony_ci * __vxge_hw_ring_block_next_pointer_set - Sets the next block pointer
20078c2ecf20Sopenharmony_ci * in RxD block
20088c2ecf20Sopenharmony_ci * Sets the next block pointer in RxD block
20098c2ecf20Sopenharmony_ci */
20108c2ecf20Sopenharmony_cistatic inline void
20118c2ecf20Sopenharmony_ci__vxge_hw_ring_block_next_pointer_set(u8 *block, dma_addr_t dma_next)
20128c2ecf20Sopenharmony_ci{
20138c2ecf20Sopenharmony_ci	*((u64 *)(block + VXGE_HW_RING_NEXT_BLOCK_POINTER_OFFSET)) = dma_next;
20148c2ecf20Sopenharmony_ci}
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci/*
20178c2ecf20Sopenharmony_ci * __vxge_hw_ring_first_block_address_get - Returns the dma address of the
20188c2ecf20Sopenharmony_ci *             first block
20198c2ecf20Sopenharmony_ci * Returns the dma address of the first RxD block
20208c2ecf20Sopenharmony_ci */
20218c2ecf20Sopenharmony_cistatic u64 __vxge_hw_ring_first_block_address_get(struct __vxge_hw_ring *ring)
20228c2ecf20Sopenharmony_ci{
20238c2ecf20Sopenharmony_ci	struct vxge_hw_mempool_dma *dma_object;
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	dma_object = ring->mempool->memblocks_dma_arr;
20268c2ecf20Sopenharmony_ci	vxge_assert(dma_object != NULL);
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	return dma_object->addr;
20298c2ecf20Sopenharmony_ci}
20308c2ecf20Sopenharmony_ci
20318c2ecf20Sopenharmony_ci/*
20328c2ecf20Sopenharmony_ci * __vxge_hw_ring_item_dma_addr - Return the dma address of an item
20338c2ecf20Sopenharmony_ci * This function returns the dma address of a given item
20348c2ecf20Sopenharmony_ci */
20358c2ecf20Sopenharmony_cistatic dma_addr_t __vxge_hw_ring_item_dma_addr(struct vxge_hw_mempool *mempoolh,
20368c2ecf20Sopenharmony_ci					       void *item)
20378c2ecf20Sopenharmony_ci{
20388c2ecf20Sopenharmony_ci	u32 memblock_idx;
20398c2ecf20Sopenharmony_ci	void *memblock;
20408c2ecf20Sopenharmony_ci	struct vxge_hw_mempool_dma *memblock_dma_object;
20418c2ecf20Sopenharmony_ci	ptrdiff_t dma_item_offset;
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci	/* get owner memblock index */
20448c2ecf20Sopenharmony_ci	memblock_idx = __vxge_hw_ring_block_memblock_idx(item);
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci	/* get owner memblock by memblock index */
20478c2ecf20Sopenharmony_ci	memblock = mempoolh->memblocks_arr[memblock_idx];
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_ci	/* get memblock DMA object by memblock index */
20508c2ecf20Sopenharmony_ci	memblock_dma_object = mempoolh->memblocks_dma_arr + memblock_idx;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	/* calculate offset in the memblock of this item */
20538c2ecf20Sopenharmony_ci	dma_item_offset = (u8 *)item - (u8 *)memblock;
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	return memblock_dma_object->addr + dma_item_offset;
20568c2ecf20Sopenharmony_ci}
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci/*
20598c2ecf20Sopenharmony_ci * __vxge_hw_ring_rxdblock_link - Link the RxD blocks
20608c2ecf20Sopenharmony_ci * This function returns the dma address of a given item
20618c2ecf20Sopenharmony_ci */
20628c2ecf20Sopenharmony_cistatic void __vxge_hw_ring_rxdblock_link(struct vxge_hw_mempool *mempoolh,
20638c2ecf20Sopenharmony_ci					 struct __vxge_hw_ring *ring, u32 from,
20648c2ecf20Sopenharmony_ci					 u32 to)
20658c2ecf20Sopenharmony_ci{
20668c2ecf20Sopenharmony_ci	u8 *to_item , *from_item;
20678c2ecf20Sopenharmony_ci	dma_addr_t to_dma;
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci	/* get "from" RxD block */
20708c2ecf20Sopenharmony_ci	from_item = mempoolh->items_arr[from];
20718c2ecf20Sopenharmony_ci	vxge_assert(from_item);
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci	/* get "to" RxD block */
20748c2ecf20Sopenharmony_ci	to_item = mempoolh->items_arr[to];
20758c2ecf20Sopenharmony_ci	vxge_assert(to_item);
20768c2ecf20Sopenharmony_ci
20778c2ecf20Sopenharmony_ci	/* return address of the beginning of previous RxD block */
20788c2ecf20Sopenharmony_ci	to_dma = __vxge_hw_ring_item_dma_addr(mempoolh, to_item);
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ci	/* set next pointer for this RxD block to point on
20818c2ecf20Sopenharmony_ci	 * previous item's DMA start address */
20828c2ecf20Sopenharmony_ci	__vxge_hw_ring_block_next_pointer_set(from_item, to_dma);
20838c2ecf20Sopenharmony_ci}
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci/*
20868c2ecf20Sopenharmony_ci * __vxge_hw_ring_mempool_item_alloc - Allocate List blocks for RxD
20878c2ecf20Sopenharmony_ci * block callback
20888c2ecf20Sopenharmony_ci * This function is callback passed to __vxge_hw_mempool_create to create memory
20898c2ecf20Sopenharmony_ci * pool for RxD block
20908c2ecf20Sopenharmony_ci */
20918c2ecf20Sopenharmony_cistatic void
20928c2ecf20Sopenharmony_ci__vxge_hw_ring_mempool_item_alloc(struct vxge_hw_mempool *mempoolh,
20938c2ecf20Sopenharmony_ci				  u32 memblock_index,
20948c2ecf20Sopenharmony_ci				  struct vxge_hw_mempool_dma *dma_object,
20958c2ecf20Sopenharmony_ci				  u32 index, u32 is_last)
20968c2ecf20Sopenharmony_ci{
20978c2ecf20Sopenharmony_ci	u32 i;
20988c2ecf20Sopenharmony_ci	void *item = mempoolh->items_arr[index];
20998c2ecf20Sopenharmony_ci	struct __vxge_hw_ring *ring =
21008c2ecf20Sopenharmony_ci		(struct __vxge_hw_ring *)mempoolh->userdata;
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci	/* format rxds array */
21038c2ecf20Sopenharmony_ci	for (i = 0; i < ring->rxds_per_block; i++) {
21048c2ecf20Sopenharmony_ci		void *rxdblock_priv;
21058c2ecf20Sopenharmony_ci		void *uld_priv;
21068c2ecf20Sopenharmony_ci		struct vxge_hw_ring_rxd_1 *rxdp;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci		u32 reserve_index = ring->channel.reserve_ptr -
21098c2ecf20Sopenharmony_ci				(index * ring->rxds_per_block + i + 1);
21108c2ecf20Sopenharmony_ci		u32 memblock_item_idx;
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci		ring->channel.reserve_arr[reserve_index] = ((u8 *)item) +
21138c2ecf20Sopenharmony_ci						i * ring->rxd_size;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci		/* Note: memblock_item_idx is index of the item within
21168c2ecf20Sopenharmony_ci		 *       the memblock. For instance, in case of three RxD-blocks
21178c2ecf20Sopenharmony_ci		 *       per memblock this value can be 0, 1 or 2. */
21188c2ecf20Sopenharmony_ci		rxdblock_priv = __vxge_hw_mempool_item_priv(mempoolh,
21198c2ecf20Sopenharmony_ci					memblock_index, item,
21208c2ecf20Sopenharmony_ci					&memblock_item_idx);
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci		rxdp = ring->channel.reserve_arr[reserve_index];
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci		uld_priv = ((u8 *)rxdblock_priv + ring->rxd_priv_size * i);
21258c2ecf20Sopenharmony_ci
21268c2ecf20Sopenharmony_ci		/* pre-format Host_Control */
21278c2ecf20Sopenharmony_ci		rxdp->host_control = (u64)(size_t)uld_priv;
21288c2ecf20Sopenharmony_ci	}
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci	__vxge_hw_ring_block_memblock_idx_set(item, memblock_index);
21318c2ecf20Sopenharmony_ci
21328c2ecf20Sopenharmony_ci	if (is_last) {
21338c2ecf20Sopenharmony_ci		/* link last one with first one */
21348c2ecf20Sopenharmony_ci		__vxge_hw_ring_rxdblock_link(mempoolh, ring, index, 0);
21358c2ecf20Sopenharmony_ci	}
21368c2ecf20Sopenharmony_ci
21378c2ecf20Sopenharmony_ci	if (index > 0) {
21388c2ecf20Sopenharmony_ci		/* link this RxD block with previous one */
21398c2ecf20Sopenharmony_ci		__vxge_hw_ring_rxdblock_link(mempoolh, ring, index - 1, index);
21408c2ecf20Sopenharmony_ci	}
21418c2ecf20Sopenharmony_ci}
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci/*
21448c2ecf20Sopenharmony_ci * __vxge_hw_ring_replenish - Initial replenish of RxDs
21458c2ecf20Sopenharmony_ci * This function replenishes the RxDs from reserve array to work array
21468c2ecf20Sopenharmony_ci */
21478c2ecf20Sopenharmony_cistatic enum vxge_hw_status
21488c2ecf20Sopenharmony_civxge_hw_ring_replenish(struct __vxge_hw_ring *ring)
21498c2ecf20Sopenharmony_ci{
21508c2ecf20Sopenharmony_ci	void *rxd;
21518c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
21528c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	channel = &ring->channel;
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	while (vxge_hw_channel_dtr_count(channel) > 0) {
21578c2ecf20Sopenharmony_ci
21588c2ecf20Sopenharmony_ci		status = vxge_hw_ring_rxd_reserve(ring, &rxd);
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci		vxge_assert(status == VXGE_HW_OK);
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci		if (ring->rxd_init) {
21638c2ecf20Sopenharmony_ci			status = ring->rxd_init(rxd, channel->userdata);
21648c2ecf20Sopenharmony_ci			if (status != VXGE_HW_OK) {
21658c2ecf20Sopenharmony_ci				vxge_hw_ring_rxd_free(ring, rxd);
21668c2ecf20Sopenharmony_ci				goto exit;
21678c2ecf20Sopenharmony_ci			}
21688c2ecf20Sopenharmony_ci		}
21698c2ecf20Sopenharmony_ci
21708c2ecf20Sopenharmony_ci		vxge_hw_ring_rxd_post(ring, rxd);
21718c2ecf20Sopenharmony_ci	}
21728c2ecf20Sopenharmony_ci	status = VXGE_HW_OK;
21738c2ecf20Sopenharmony_ciexit:
21748c2ecf20Sopenharmony_ci	return status;
21758c2ecf20Sopenharmony_ci}
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci/*
21788c2ecf20Sopenharmony_ci * __vxge_hw_channel_allocate - Allocate memory for channel
21798c2ecf20Sopenharmony_ci * This function allocates required memory for the channel and various arrays
21808c2ecf20Sopenharmony_ci * in the channel
21818c2ecf20Sopenharmony_ci */
21828c2ecf20Sopenharmony_cistatic struct __vxge_hw_channel *
21838c2ecf20Sopenharmony_ci__vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
21848c2ecf20Sopenharmony_ci			   enum __vxge_hw_channel_type type,
21858c2ecf20Sopenharmony_ci			   u32 length, u32 per_dtr_space,
21868c2ecf20Sopenharmony_ci			   void *userdata)
21878c2ecf20Sopenharmony_ci{
21888c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
21898c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev;
21908c2ecf20Sopenharmony_ci	int size = 0;
21918c2ecf20Sopenharmony_ci	u32 vp_id;
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci	hldev = vph->vpath->hldev;
21948c2ecf20Sopenharmony_ci	vp_id = vph->vpath->vp_id;
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci	switch (type) {
21978c2ecf20Sopenharmony_ci	case VXGE_HW_CHANNEL_TYPE_FIFO:
21988c2ecf20Sopenharmony_ci		size = sizeof(struct __vxge_hw_fifo);
21998c2ecf20Sopenharmony_ci		break;
22008c2ecf20Sopenharmony_ci	case VXGE_HW_CHANNEL_TYPE_RING:
22018c2ecf20Sopenharmony_ci		size = sizeof(struct __vxge_hw_ring);
22028c2ecf20Sopenharmony_ci		break;
22038c2ecf20Sopenharmony_ci	default:
22048c2ecf20Sopenharmony_ci		break;
22058c2ecf20Sopenharmony_ci	}
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	channel = kzalloc(size, GFP_KERNEL);
22088c2ecf20Sopenharmony_ci	if (channel == NULL)
22098c2ecf20Sopenharmony_ci		goto exit0;
22108c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&channel->item);
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	channel->common_reg = hldev->common_reg;
22138c2ecf20Sopenharmony_ci	channel->first_vp_id = hldev->first_vp_id;
22148c2ecf20Sopenharmony_ci	channel->type = type;
22158c2ecf20Sopenharmony_ci	channel->devh = hldev;
22168c2ecf20Sopenharmony_ci	channel->vph = vph;
22178c2ecf20Sopenharmony_ci	channel->userdata = userdata;
22188c2ecf20Sopenharmony_ci	channel->per_dtr_space = per_dtr_space;
22198c2ecf20Sopenharmony_ci	channel->length = length;
22208c2ecf20Sopenharmony_ci	channel->vp_id = vp_id;
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_ci	channel->work_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
22238c2ecf20Sopenharmony_ci	if (channel->work_arr == NULL)
22248c2ecf20Sopenharmony_ci		goto exit1;
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci	channel->free_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
22278c2ecf20Sopenharmony_ci	if (channel->free_arr == NULL)
22288c2ecf20Sopenharmony_ci		goto exit1;
22298c2ecf20Sopenharmony_ci	channel->free_ptr = length;
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_ci	channel->reserve_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
22328c2ecf20Sopenharmony_ci	if (channel->reserve_arr == NULL)
22338c2ecf20Sopenharmony_ci		goto exit1;
22348c2ecf20Sopenharmony_ci	channel->reserve_ptr = length;
22358c2ecf20Sopenharmony_ci	channel->reserve_top = 0;
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci	channel->orig_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
22388c2ecf20Sopenharmony_ci	if (channel->orig_arr == NULL)
22398c2ecf20Sopenharmony_ci		goto exit1;
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	return channel;
22428c2ecf20Sopenharmony_ciexit1:
22438c2ecf20Sopenharmony_ci	__vxge_hw_channel_free(channel);
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ciexit0:
22468c2ecf20Sopenharmony_ci	return NULL;
22478c2ecf20Sopenharmony_ci}
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_ci/*
22508c2ecf20Sopenharmony_ci * vxge_hw_blockpool_block_add - callback for vxge_os_dma_malloc_async
22518c2ecf20Sopenharmony_ci * Adds a block to block pool
22528c2ecf20Sopenharmony_ci */
22538c2ecf20Sopenharmony_cistatic void vxge_hw_blockpool_block_add(struct __vxge_hw_device *devh,
22548c2ecf20Sopenharmony_ci					void *block_addr,
22558c2ecf20Sopenharmony_ci					u32 length,
22568c2ecf20Sopenharmony_ci					struct pci_dev *dma_h,
22578c2ecf20Sopenharmony_ci					struct pci_dev *acc_handle)
22588c2ecf20Sopenharmony_ci{
22598c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool *blockpool;
22608c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool_entry *entry = NULL;
22618c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci	blockpool = &devh->block_pool;
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci	if (block_addr == NULL) {
22668c2ecf20Sopenharmony_ci		blockpool->req_out--;
22678c2ecf20Sopenharmony_ci		goto exit;
22688c2ecf20Sopenharmony_ci	}
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci	dma_addr = dma_map_single(&devh->pdev->dev, block_addr, length,
22718c2ecf20Sopenharmony_ci				  DMA_BIDIRECTIONAL);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(&devh->pdev->dev, dma_addr))) {
22748c2ecf20Sopenharmony_ci		vxge_os_dma_free(devh->pdev, block_addr, &acc_handle);
22758c2ecf20Sopenharmony_ci		blockpool->req_out--;
22768c2ecf20Sopenharmony_ci		goto exit;
22778c2ecf20Sopenharmony_ci	}
22788c2ecf20Sopenharmony_ci
22798c2ecf20Sopenharmony_ci	if (!list_empty(&blockpool->free_entry_list))
22808c2ecf20Sopenharmony_ci		entry = (struct __vxge_hw_blockpool_entry *)
22818c2ecf20Sopenharmony_ci			list_first_entry(&blockpool->free_entry_list,
22828c2ecf20Sopenharmony_ci				struct __vxge_hw_blockpool_entry,
22838c2ecf20Sopenharmony_ci				item);
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci	if (entry == NULL)
22868c2ecf20Sopenharmony_ci		entry =	vmalloc(sizeof(struct __vxge_hw_blockpool_entry));
22878c2ecf20Sopenharmony_ci	else
22888c2ecf20Sopenharmony_ci		list_del(&entry->item);
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	if (entry) {
22918c2ecf20Sopenharmony_ci		entry->length = length;
22928c2ecf20Sopenharmony_ci		entry->memblock = block_addr;
22938c2ecf20Sopenharmony_ci		entry->dma_addr = dma_addr;
22948c2ecf20Sopenharmony_ci		entry->acc_handle = acc_handle;
22958c2ecf20Sopenharmony_ci		entry->dma_handle = dma_h;
22968c2ecf20Sopenharmony_ci		list_add(&entry->item, &blockpool->free_block_list);
22978c2ecf20Sopenharmony_ci		blockpool->pool_size++;
22988c2ecf20Sopenharmony_ci	}
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_ci	blockpool->req_out--;
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ciexit:
23038c2ecf20Sopenharmony_ci	return;
23048c2ecf20Sopenharmony_ci}
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_cistatic inline void
23078c2ecf20Sopenharmony_civxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh, unsigned long size)
23088c2ecf20Sopenharmony_ci{
23098c2ecf20Sopenharmony_ci	void *vaddr;
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci	vaddr = kmalloc(size, GFP_KERNEL | GFP_DMA);
23128c2ecf20Sopenharmony_ci	vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev);
23138c2ecf20Sopenharmony_ci}
23148c2ecf20Sopenharmony_ci
23158c2ecf20Sopenharmony_ci/*
23168c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_blocks_add - Request additional blocks
23178c2ecf20Sopenharmony_ci */
23188c2ecf20Sopenharmony_cistatic
23198c2ecf20Sopenharmony_civoid __vxge_hw_blockpool_blocks_add(struct __vxge_hw_blockpool *blockpool)
23208c2ecf20Sopenharmony_ci{
23218c2ecf20Sopenharmony_ci	u32 nreq = 0, i;
23228c2ecf20Sopenharmony_ci
23238c2ecf20Sopenharmony_ci	if ((blockpool->pool_size  +  blockpool->req_out) <
23248c2ecf20Sopenharmony_ci		VXGE_HW_MIN_DMA_BLOCK_POOL_SIZE) {
23258c2ecf20Sopenharmony_ci		nreq = VXGE_HW_INCR_DMA_BLOCK_POOL_SIZE;
23268c2ecf20Sopenharmony_ci		blockpool->req_out += nreq;
23278c2ecf20Sopenharmony_ci	}
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_ci	for (i = 0; i < nreq; i++)
23308c2ecf20Sopenharmony_ci		vxge_os_dma_malloc_async(
23318c2ecf20Sopenharmony_ci			(blockpool->hldev)->pdev,
23328c2ecf20Sopenharmony_ci			blockpool->hldev, VXGE_HW_BLOCK_SIZE);
23338c2ecf20Sopenharmony_ci}
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci/*
23368c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_malloc - Allocate a memory block from pool
23378c2ecf20Sopenharmony_ci * Allocates a block of memory of given size, either from block pool
23388c2ecf20Sopenharmony_ci * or by calling vxge_os_dma_malloc()
23398c2ecf20Sopenharmony_ci */
23408c2ecf20Sopenharmony_cistatic void *__vxge_hw_blockpool_malloc(struct __vxge_hw_device *devh, u32 size,
23418c2ecf20Sopenharmony_ci					struct vxge_hw_mempool_dma *dma_object)
23428c2ecf20Sopenharmony_ci{
23438c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool_entry *entry = NULL;
23448c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool  *blockpool;
23458c2ecf20Sopenharmony_ci	void *memblock = NULL;
23468c2ecf20Sopenharmony_ci
23478c2ecf20Sopenharmony_ci	blockpool = &devh->block_pool;
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci	if (size != blockpool->block_size) {
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci		memblock = vxge_os_dma_malloc(devh->pdev, size,
23528c2ecf20Sopenharmony_ci						&dma_object->handle,
23538c2ecf20Sopenharmony_ci						&dma_object->acc_handle);
23548c2ecf20Sopenharmony_ci
23558c2ecf20Sopenharmony_ci		if (!memblock)
23568c2ecf20Sopenharmony_ci			goto exit;
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_ci		dma_object->addr = dma_map_single(&devh->pdev->dev, memblock,
23598c2ecf20Sopenharmony_ci						  size, DMA_BIDIRECTIONAL);
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci		if (unlikely(dma_mapping_error(&devh->pdev->dev, dma_object->addr))) {
23628c2ecf20Sopenharmony_ci			vxge_os_dma_free(devh->pdev, memblock,
23638c2ecf20Sopenharmony_ci				&dma_object->acc_handle);
23648c2ecf20Sopenharmony_ci			memblock = NULL;
23658c2ecf20Sopenharmony_ci			goto exit;
23668c2ecf20Sopenharmony_ci		}
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci	} else {
23698c2ecf20Sopenharmony_ci
23708c2ecf20Sopenharmony_ci		if (!list_empty(&blockpool->free_block_list))
23718c2ecf20Sopenharmony_ci			entry = (struct __vxge_hw_blockpool_entry *)
23728c2ecf20Sopenharmony_ci				list_first_entry(&blockpool->free_block_list,
23738c2ecf20Sopenharmony_ci					struct __vxge_hw_blockpool_entry,
23748c2ecf20Sopenharmony_ci					item);
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci		if (entry != NULL) {
23778c2ecf20Sopenharmony_ci			list_del(&entry->item);
23788c2ecf20Sopenharmony_ci			dma_object->addr = entry->dma_addr;
23798c2ecf20Sopenharmony_ci			dma_object->handle = entry->dma_handle;
23808c2ecf20Sopenharmony_ci			dma_object->acc_handle = entry->acc_handle;
23818c2ecf20Sopenharmony_ci			memblock = entry->memblock;
23828c2ecf20Sopenharmony_ci
23838c2ecf20Sopenharmony_ci			list_add(&entry->item,
23848c2ecf20Sopenharmony_ci				&blockpool->free_entry_list);
23858c2ecf20Sopenharmony_ci			blockpool->pool_size--;
23868c2ecf20Sopenharmony_ci		}
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_ci		if (memblock != NULL)
23898c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_blocks_add(blockpool);
23908c2ecf20Sopenharmony_ci	}
23918c2ecf20Sopenharmony_ciexit:
23928c2ecf20Sopenharmony_ci	return memblock;
23938c2ecf20Sopenharmony_ci}
23948c2ecf20Sopenharmony_ci
23958c2ecf20Sopenharmony_ci/*
23968c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_blocks_remove - Free additional blocks
23978c2ecf20Sopenharmony_ci */
23988c2ecf20Sopenharmony_cistatic void
23998c2ecf20Sopenharmony_ci__vxge_hw_blockpool_blocks_remove(struct __vxge_hw_blockpool *blockpool)
24008c2ecf20Sopenharmony_ci{
24018c2ecf20Sopenharmony_ci	struct list_head *p, *n;
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	list_for_each_safe(p, n, &blockpool->free_block_list) {
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci		if (blockpool->pool_size < blockpool->pool_max)
24068c2ecf20Sopenharmony_ci			break;
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci		dma_unmap_single(&(blockpool->hldev)->pdev->dev,
24098c2ecf20Sopenharmony_ci				 ((struct __vxge_hw_blockpool_entry *)p)->dma_addr,
24108c2ecf20Sopenharmony_ci				 ((struct __vxge_hw_blockpool_entry *)p)->length,
24118c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_ci		vxge_os_dma_free(
24148c2ecf20Sopenharmony_ci			(blockpool->hldev)->pdev,
24158c2ecf20Sopenharmony_ci			((struct __vxge_hw_blockpool_entry *)p)->memblock,
24168c2ecf20Sopenharmony_ci			&((struct __vxge_hw_blockpool_entry *)p)->acc_handle);
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci		list_del(&((struct __vxge_hw_blockpool_entry *)p)->item);
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci		list_add(p, &blockpool->free_entry_list);
24218c2ecf20Sopenharmony_ci
24228c2ecf20Sopenharmony_ci		blockpool->pool_size--;
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci	}
24258c2ecf20Sopenharmony_ci}
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci/*
24288c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_free - Frees the memory allcoated with
24298c2ecf20Sopenharmony_ci *				__vxge_hw_blockpool_malloc
24308c2ecf20Sopenharmony_ci */
24318c2ecf20Sopenharmony_cistatic void __vxge_hw_blockpool_free(struct __vxge_hw_device *devh,
24328c2ecf20Sopenharmony_ci				     void *memblock, u32 size,
24338c2ecf20Sopenharmony_ci				     struct vxge_hw_mempool_dma *dma_object)
24348c2ecf20Sopenharmony_ci{
24358c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool_entry *entry = NULL;
24368c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool  *blockpool;
24378c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	blockpool = &devh->block_pool;
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_ci	if (size != blockpool->block_size) {
24428c2ecf20Sopenharmony_ci		dma_unmap_single(&devh->pdev->dev, dma_object->addr, size,
24438c2ecf20Sopenharmony_ci				 DMA_BIDIRECTIONAL);
24448c2ecf20Sopenharmony_ci		vxge_os_dma_free(devh->pdev, memblock, &dma_object->acc_handle);
24458c2ecf20Sopenharmony_ci	} else {
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci		if (!list_empty(&blockpool->free_entry_list))
24488c2ecf20Sopenharmony_ci			entry = (struct __vxge_hw_blockpool_entry *)
24498c2ecf20Sopenharmony_ci				list_first_entry(&blockpool->free_entry_list,
24508c2ecf20Sopenharmony_ci					struct __vxge_hw_blockpool_entry,
24518c2ecf20Sopenharmony_ci					item);
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci		if (entry == NULL)
24548c2ecf20Sopenharmony_ci			entry =	vmalloc(sizeof(
24558c2ecf20Sopenharmony_ci					struct __vxge_hw_blockpool_entry));
24568c2ecf20Sopenharmony_ci		else
24578c2ecf20Sopenharmony_ci			list_del(&entry->item);
24588c2ecf20Sopenharmony_ci
24598c2ecf20Sopenharmony_ci		if (entry != NULL) {
24608c2ecf20Sopenharmony_ci			entry->length = size;
24618c2ecf20Sopenharmony_ci			entry->memblock = memblock;
24628c2ecf20Sopenharmony_ci			entry->dma_addr = dma_object->addr;
24638c2ecf20Sopenharmony_ci			entry->acc_handle = dma_object->acc_handle;
24648c2ecf20Sopenharmony_ci			entry->dma_handle = dma_object->handle;
24658c2ecf20Sopenharmony_ci			list_add(&entry->item,
24668c2ecf20Sopenharmony_ci					&blockpool->free_block_list);
24678c2ecf20Sopenharmony_ci			blockpool->pool_size++;
24688c2ecf20Sopenharmony_ci			status = VXGE_HW_OK;
24698c2ecf20Sopenharmony_ci		} else
24708c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
24718c2ecf20Sopenharmony_ci
24728c2ecf20Sopenharmony_ci		if (status == VXGE_HW_OK)
24738c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_blocks_remove(blockpool);
24748c2ecf20Sopenharmony_ci	}
24758c2ecf20Sopenharmony_ci}
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_ci/*
24788c2ecf20Sopenharmony_ci * vxge_hw_mempool_destroy
24798c2ecf20Sopenharmony_ci */
24808c2ecf20Sopenharmony_cistatic void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool)
24818c2ecf20Sopenharmony_ci{
24828c2ecf20Sopenharmony_ci	u32 i, j;
24838c2ecf20Sopenharmony_ci	struct __vxge_hw_device *devh = mempool->devh;
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_ci	for (i = 0; i < mempool->memblocks_allocated; i++) {
24868c2ecf20Sopenharmony_ci		struct vxge_hw_mempool_dma *dma_object;
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_ci		vxge_assert(mempool->memblocks_arr[i]);
24898c2ecf20Sopenharmony_ci		vxge_assert(mempool->memblocks_dma_arr + i);
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci		dma_object = mempool->memblocks_dma_arr + i;
24928c2ecf20Sopenharmony_ci
24938c2ecf20Sopenharmony_ci		for (j = 0; j < mempool->items_per_memblock; j++) {
24948c2ecf20Sopenharmony_ci			u32 index = i * mempool->items_per_memblock + j;
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci			/* to skip last partially filled(if any) memblock */
24978c2ecf20Sopenharmony_ci			if (index >= mempool->items_current)
24988c2ecf20Sopenharmony_ci				break;
24998c2ecf20Sopenharmony_ci		}
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci		vfree(mempool->memblocks_priv_arr[i]);
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_ci		__vxge_hw_blockpool_free(devh, mempool->memblocks_arr[i],
25048c2ecf20Sopenharmony_ci				mempool->memblock_size, dma_object);
25058c2ecf20Sopenharmony_ci	}
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_ci	vfree(mempool->items_arr);
25088c2ecf20Sopenharmony_ci	vfree(mempool->memblocks_dma_arr);
25098c2ecf20Sopenharmony_ci	vfree(mempool->memblocks_priv_arr);
25108c2ecf20Sopenharmony_ci	vfree(mempool->memblocks_arr);
25118c2ecf20Sopenharmony_ci	vfree(mempool);
25128c2ecf20Sopenharmony_ci}
25138c2ecf20Sopenharmony_ci
25148c2ecf20Sopenharmony_ci/*
25158c2ecf20Sopenharmony_ci * __vxge_hw_mempool_grow
25168c2ecf20Sopenharmony_ci * Will resize mempool up to %num_allocate value.
25178c2ecf20Sopenharmony_ci */
25188c2ecf20Sopenharmony_cistatic enum vxge_hw_status
25198c2ecf20Sopenharmony_ci__vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate,
25208c2ecf20Sopenharmony_ci		       u32 *num_allocated)
25218c2ecf20Sopenharmony_ci{
25228c2ecf20Sopenharmony_ci	u32 i, first_time = mempool->memblocks_allocated == 0 ? 1 : 0;
25238c2ecf20Sopenharmony_ci	u32 n_items = mempool->items_per_memblock;
25248c2ecf20Sopenharmony_ci	u32 start_block_idx = mempool->memblocks_allocated;
25258c2ecf20Sopenharmony_ci	u32 end_block_idx = mempool->memblocks_allocated + num_allocate;
25268c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	*num_allocated = 0;
25298c2ecf20Sopenharmony_ci
25308c2ecf20Sopenharmony_ci	if (end_block_idx > mempool->memblocks_max) {
25318c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
25328c2ecf20Sopenharmony_ci		goto exit;
25338c2ecf20Sopenharmony_ci	}
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	for (i = start_block_idx; i < end_block_idx; i++) {
25368c2ecf20Sopenharmony_ci		u32 j;
25378c2ecf20Sopenharmony_ci		u32 is_last = ((end_block_idx - 1) == i);
25388c2ecf20Sopenharmony_ci		struct vxge_hw_mempool_dma *dma_object =
25398c2ecf20Sopenharmony_ci			mempool->memblocks_dma_arr + i;
25408c2ecf20Sopenharmony_ci		void *the_memblock;
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci		/* allocate memblock's private part. Each DMA memblock
25438c2ecf20Sopenharmony_ci		 * has a space allocated for item's private usage upon
25448c2ecf20Sopenharmony_ci		 * mempool's user request. Each time mempool grows, it will
25458c2ecf20Sopenharmony_ci		 * allocate new memblock and its private part at once.
25468c2ecf20Sopenharmony_ci		 * This helps to minimize memory usage a lot. */
25478c2ecf20Sopenharmony_ci		mempool->memblocks_priv_arr[i] =
25488c2ecf20Sopenharmony_ci			vzalloc(array_size(mempool->items_priv_size, n_items));
25498c2ecf20Sopenharmony_ci		if (mempool->memblocks_priv_arr[i] == NULL) {
25508c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
25518c2ecf20Sopenharmony_ci			goto exit;
25528c2ecf20Sopenharmony_ci		}
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci		/* allocate DMA-capable memblock */
25558c2ecf20Sopenharmony_ci		mempool->memblocks_arr[i] =
25568c2ecf20Sopenharmony_ci			__vxge_hw_blockpool_malloc(mempool->devh,
25578c2ecf20Sopenharmony_ci				mempool->memblock_size, dma_object);
25588c2ecf20Sopenharmony_ci		if (mempool->memblocks_arr[i] == NULL) {
25598c2ecf20Sopenharmony_ci			vfree(mempool->memblocks_priv_arr[i]);
25608c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_OUT_OF_MEMORY;
25618c2ecf20Sopenharmony_ci			goto exit;
25628c2ecf20Sopenharmony_ci		}
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci		(*num_allocated)++;
25658c2ecf20Sopenharmony_ci		mempool->memblocks_allocated++;
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci		memset(mempool->memblocks_arr[i], 0, mempool->memblock_size);
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci		the_memblock = mempool->memblocks_arr[i];
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci		/* fill the items hash array */
25728c2ecf20Sopenharmony_ci		for (j = 0; j < n_items; j++) {
25738c2ecf20Sopenharmony_ci			u32 index = i * n_items + j;
25748c2ecf20Sopenharmony_ci
25758c2ecf20Sopenharmony_ci			if (first_time && index >= mempool->items_initial)
25768c2ecf20Sopenharmony_ci				break;
25778c2ecf20Sopenharmony_ci
25788c2ecf20Sopenharmony_ci			mempool->items_arr[index] =
25798c2ecf20Sopenharmony_ci				((char *)the_memblock + j*mempool->item_size);
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci			/* let caller to do more job on each item */
25828c2ecf20Sopenharmony_ci			if (mempool->item_func_alloc != NULL)
25838c2ecf20Sopenharmony_ci				mempool->item_func_alloc(mempool, i,
25848c2ecf20Sopenharmony_ci					dma_object, index, is_last);
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci			mempool->items_current = index + 1;
25878c2ecf20Sopenharmony_ci		}
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ci		if (first_time && mempool->items_current ==
25908c2ecf20Sopenharmony_ci					mempool->items_initial)
25918c2ecf20Sopenharmony_ci			break;
25928c2ecf20Sopenharmony_ci	}
25938c2ecf20Sopenharmony_ciexit:
25948c2ecf20Sopenharmony_ci	return status;
25958c2ecf20Sopenharmony_ci}
25968c2ecf20Sopenharmony_ci
25978c2ecf20Sopenharmony_ci/*
25988c2ecf20Sopenharmony_ci * vxge_hw_mempool_create
25998c2ecf20Sopenharmony_ci * This function will create memory pool object. Pool may grow but will
26008c2ecf20Sopenharmony_ci * never shrink. Pool consists of number of dynamically allocated blocks
26018c2ecf20Sopenharmony_ci * with size enough to hold %items_initial number of items. Memory is
26028c2ecf20Sopenharmony_ci * DMA-able but client must map/unmap before interoperating with the device.
26038c2ecf20Sopenharmony_ci */
26048c2ecf20Sopenharmony_cistatic struct vxge_hw_mempool *
26058c2ecf20Sopenharmony_ci__vxge_hw_mempool_create(struct __vxge_hw_device *devh,
26068c2ecf20Sopenharmony_ci			 u32 memblock_size,
26078c2ecf20Sopenharmony_ci			 u32 item_size,
26088c2ecf20Sopenharmony_ci			 u32 items_priv_size,
26098c2ecf20Sopenharmony_ci			 u32 items_initial,
26108c2ecf20Sopenharmony_ci			 u32 items_max,
26118c2ecf20Sopenharmony_ci			 const struct vxge_hw_mempool_cbs *mp_callback,
26128c2ecf20Sopenharmony_ci			 void *userdata)
26138c2ecf20Sopenharmony_ci{
26148c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
26158c2ecf20Sopenharmony_ci	u32 memblocks_to_allocate;
26168c2ecf20Sopenharmony_ci	struct vxge_hw_mempool *mempool = NULL;
26178c2ecf20Sopenharmony_ci	u32 allocated;
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_ci	if (memblock_size < item_size) {
26208c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
26218c2ecf20Sopenharmony_ci		goto exit;
26228c2ecf20Sopenharmony_ci	}
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	mempool = vzalloc(sizeof(struct vxge_hw_mempool));
26258c2ecf20Sopenharmony_ci	if (mempool == NULL) {
26268c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
26278c2ecf20Sopenharmony_ci		goto exit;
26288c2ecf20Sopenharmony_ci	}
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_ci	mempool->devh			= devh;
26318c2ecf20Sopenharmony_ci	mempool->memblock_size		= memblock_size;
26328c2ecf20Sopenharmony_ci	mempool->items_max		= items_max;
26338c2ecf20Sopenharmony_ci	mempool->items_initial		= items_initial;
26348c2ecf20Sopenharmony_ci	mempool->item_size		= item_size;
26358c2ecf20Sopenharmony_ci	mempool->items_priv_size	= items_priv_size;
26368c2ecf20Sopenharmony_ci	mempool->item_func_alloc	= mp_callback->item_func_alloc;
26378c2ecf20Sopenharmony_ci	mempool->userdata		= userdata;
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci	mempool->memblocks_allocated = 0;
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci	mempool->items_per_memblock = memblock_size / item_size;
26428c2ecf20Sopenharmony_ci
26438c2ecf20Sopenharmony_ci	mempool->memblocks_max = (items_max + mempool->items_per_memblock - 1) /
26448c2ecf20Sopenharmony_ci					mempool->items_per_memblock;
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_ci	/* allocate array of memblocks */
26478c2ecf20Sopenharmony_ci	mempool->memblocks_arr =
26488c2ecf20Sopenharmony_ci		vzalloc(array_size(sizeof(void *), mempool->memblocks_max));
26498c2ecf20Sopenharmony_ci	if (mempool->memblocks_arr == NULL) {
26508c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(mempool);
26518c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
26528c2ecf20Sopenharmony_ci		mempool = NULL;
26538c2ecf20Sopenharmony_ci		goto exit;
26548c2ecf20Sopenharmony_ci	}
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	/* allocate array of private parts of items per memblocks */
26578c2ecf20Sopenharmony_ci	mempool->memblocks_priv_arr =
26588c2ecf20Sopenharmony_ci		vzalloc(array_size(sizeof(void *), mempool->memblocks_max));
26598c2ecf20Sopenharmony_ci	if (mempool->memblocks_priv_arr == NULL) {
26608c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(mempool);
26618c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
26628c2ecf20Sopenharmony_ci		mempool = NULL;
26638c2ecf20Sopenharmony_ci		goto exit;
26648c2ecf20Sopenharmony_ci	}
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_ci	/* allocate array of memblocks DMA objects */
26678c2ecf20Sopenharmony_ci	mempool->memblocks_dma_arr =
26688c2ecf20Sopenharmony_ci		vzalloc(array_size(sizeof(struct vxge_hw_mempool_dma),
26698c2ecf20Sopenharmony_ci				   mempool->memblocks_max));
26708c2ecf20Sopenharmony_ci	if (mempool->memblocks_dma_arr == NULL) {
26718c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(mempool);
26728c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
26738c2ecf20Sopenharmony_ci		mempool = NULL;
26748c2ecf20Sopenharmony_ci		goto exit;
26758c2ecf20Sopenharmony_ci	}
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci	/* allocate hash array of items */
26788c2ecf20Sopenharmony_ci	mempool->items_arr = vzalloc(array_size(sizeof(void *),
26798c2ecf20Sopenharmony_ci						mempool->items_max));
26808c2ecf20Sopenharmony_ci	if (mempool->items_arr == NULL) {
26818c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(mempool);
26828c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
26838c2ecf20Sopenharmony_ci		mempool = NULL;
26848c2ecf20Sopenharmony_ci		goto exit;
26858c2ecf20Sopenharmony_ci	}
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ci	/* calculate initial number of memblocks */
26888c2ecf20Sopenharmony_ci	memblocks_to_allocate = (mempool->items_initial +
26898c2ecf20Sopenharmony_ci				 mempool->items_per_memblock - 1) /
26908c2ecf20Sopenharmony_ci						mempool->items_per_memblock;
26918c2ecf20Sopenharmony_ci
26928c2ecf20Sopenharmony_ci	/* pre-allocate the mempool */
26938c2ecf20Sopenharmony_ci	status = __vxge_hw_mempool_grow(mempool, memblocks_to_allocate,
26948c2ecf20Sopenharmony_ci					&allocated);
26958c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
26968c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(mempool);
26978c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
26988c2ecf20Sopenharmony_ci		mempool = NULL;
26998c2ecf20Sopenharmony_ci		goto exit;
27008c2ecf20Sopenharmony_ci	}
27018c2ecf20Sopenharmony_ci
27028c2ecf20Sopenharmony_ciexit:
27038c2ecf20Sopenharmony_ci	return mempool;
27048c2ecf20Sopenharmony_ci}
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_ci/*
27078c2ecf20Sopenharmony_ci * __vxge_hw_ring_abort - Returns the RxD
27088c2ecf20Sopenharmony_ci * This function terminates the RxDs of ring
27098c2ecf20Sopenharmony_ci */
27108c2ecf20Sopenharmony_cistatic enum vxge_hw_status __vxge_hw_ring_abort(struct __vxge_hw_ring *ring)
27118c2ecf20Sopenharmony_ci{
27128c2ecf20Sopenharmony_ci	void *rxdh;
27138c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
27148c2ecf20Sopenharmony_ci
27158c2ecf20Sopenharmony_ci	channel = &ring->channel;
27168c2ecf20Sopenharmony_ci
27178c2ecf20Sopenharmony_ci	for (;;) {
27188c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_try_complete(channel, &rxdh);
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_ci		if (rxdh == NULL)
27218c2ecf20Sopenharmony_ci			break;
27228c2ecf20Sopenharmony_ci
27238c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_complete(channel);
27248c2ecf20Sopenharmony_ci
27258c2ecf20Sopenharmony_ci		if (ring->rxd_term)
27268c2ecf20Sopenharmony_ci			ring->rxd_term(rxdh, VXGE_HW_RXD_STATE_POSTED,
27278c2ecf20Sopenharmony_ci				channel->userdata);
27288c2ecf20Sopenharmony_ci
27298c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_free(channel, rxdh);
27308c2ecf20Sopenharmony_ci	}
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
27338c2ecf20Sopenharmony_ci}
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci/*
27368c2ecf20Sopenharmony_ci * __vxge_hw_ring_reset - Resets the ring
27378c2ecf20Sopenharmony_ci * This function resets the ring during vpath reset operation
27388c2ecf20Sopenharmony_ci */
27398c2ecf20Sopenharmony_cistatic enum vxge_hw_status __vxge_hw_ring_reset(struct __vxge_hw_ring *ring)
27408c2ecf20Sopenharmony_ci{
27418c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
27428c2ecf20Sopenharmony_ci	struct __vxge_hw_channel *channel;
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_ci	channel = &ring->channel;
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	__vxge_hw_ring_abort(ring);
27478c2ecf20Sopenharmony_ci
27488c2ecf20Sopenharmony_ci	status = __vxge_hw_channel_reset(channel);
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
27518c2ecf20Sopenharmony_ci		goto exit;
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_ci	if (ring->rxd_init) {
27548c2ecf20Sopenharmony_ci		status = vxge_hw_ring_replenish(ring);
27558c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
27568c2ecf20Sopenharmony_ci			goto exit;
27578c2ecf20Sopenharmony_ci	}
27588c2ecf20Sopenharmony_ciexit:
27598c2ecf20Sopenharmony_ci	return status;
27608c2ecf20Sopenharmony_ci}
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci/*
27638c2ecf20Sopenharmony_ci * __vxge_hw_ring_delete - Removes the ring
27648c2ecf20Sopenharmony_ci * This function freeup the memory pool and removes the ring
27658c2ecf20Sopenharmony_ci */
27668c2ecf20Sopenharmony_cistatic enum vxge_hw_status
27678c2ecf20Sopenharmony_ci__vxge_hw_ring_delete(struct __vxge_hw_vpath_handle *vp)
27688c2ecf20Sopenharmony_ci{
27698c2ecf20Sopenharmony_ci	struct __vxge_hw_ring *ring = vp->vpath->ringh;
27708c2ecf20Sopenharmony_ci
27718c2ecf20Sopenharmony_ci	__vxge_hw_ring_abort(ring);
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	if (ring->mempool)
27748c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(ring->mempool);
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	vp->vpath->ringh = NULL;
27778c2ecf20Sopenharmony_ci	__vxge_hw_channel_free(&ring->channel);
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
27808c2ecf20Sopenharmony_ci}
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_ci/*
27838c2ecf20Sopenharmony_ci * __vxge_hw_ring_create - Create a Ring
27848c2ecf20Sopenharmony_ci * This function creates Ring and initializes it.
27858c2ecf20Sopenharmony_ci */
27868c2ecf20Sopenharmony_cistatic enum vxge_hw_status
27878c2ecf20Sopenharmony_ci__vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
27888c2ecf20Sopenharmony_ci		      struct vxge_hw_ring_attr *attr)
27898c2ecf20Sopenharmony_ci{
27908c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
27918c2ecf20Sopenharmony_ci	struct __vxge_hw_ring *ring;
27928c2ecf20Sopenharmony_ci	u32 ring_length;
27938c2ecf20Sopenharmony_ci	struct vxge_hw_ring_config *config;
27948c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev;
27958c2ecf20Sopenharmony_ci	u32 vp_id;
27968c2ecf20Sopenharmony_ci	static const struct vxge_hw_mempool_cbs ring_mp_callback = {
27978c2ecf20Sopenharmony_ci		.item_func_alloc = __vxge_hw_ring_mempool_item_alloc,
27988c2ecf20Sopenharmony_ci	};
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ci	if ((vp == NULL) || (attr == NULL)) {
28018c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
28028c2ecf20Sopenharmony_ci		goto exit;
28038c2ecf20Sopenharmony_ci	}
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ci	hldev = vp->vpath->hldev;
28068c2ecf20Sopenharmony_ci	vp_id = vp->vpath->vp_id;
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_ci	config = &hldev->config.vp_config[vp_id].ring;
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci	ring_length = config->ring_blocks *
28118c2ecf20Sopenharmony_ci			vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_ci	ring = (struct __vxge_hw_ring *)__vxge_hw_channel_allocate(vp,
28148c2ecf20Sopenharmony_ci						VXGE_HW_CHANNEL_TYPE_RING,
28158c2ecf20Sopenharmony_ci						ring_length,
28168c2ecf20Sopenharmony_ci						attr->per_rxd_space,
28178c2ecf20Sopenharmony_ci						attr->userdata);
28188c2ecf20Sopenharmony_ci	if (ring == NULL) {
28198c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
28208c2ecf20Sopenharmony_ci		goto exit;
28218c2ecf20Sopenharmony_ci	}
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_ci	vp->vpath->ringh = ring;
28248c2ecf20Sopenharmony_ci	ring->vp_id = vp_id;
28258c2ecf20Sopenharmony_ci	ring->vp_reg = vp->vpath->vp_reg;
28268c2ecf20Sopenharmony_ci	ring->common_reg = hldev->common_reg;
28278c2ecf20Sopenharmony_ci	ring->stats = &vp->vpath->sw_stats->ring_stats;
28288c2ecf20Sopenharmony_ci	ring->config = config;
28298c2ecf20Sopenharmony_ci	ring->callback = attr->callback;
28308c2ecf20Sopenharmony_ci	ring->rxd_init = attr->rxd_init;
28318c2ecf20Sopenharmony_ci	ring->rxd_term = attr->rxd_term;
28328c2ecf20Sopenharmony_ci	ring->buffer_mode = config->buffer_mode;
28338c2ecf20Sopenharmony_ci	ring->tim_rti_cfg1_saved = vp->vpath->tim_rti_cfg1_saved;
28348c2ecf20Sopenharmony_ci	ring->tim_rti_cfg3_saved = vp->vpath->tim_rti_cfg3_saved;
28358c2ecf20Sopenharmony_ci	ring->rxds_limit = config->rxds_limit;
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci	ring->rxd_size = vxge_hw_ring_rxd_size_get(config->buffer_mode);
28388c2ecf20Sopenharmony_ci	ring->rxd_priv_size =
28398c2ecf20Sopenharmony_ci		sizeof(struct __vxge_hw_ring_rxd_priv) + attr->per_rxd_space;
28408c2ecf20Sopenharmony_ci	ring->per_rxd_space = attr->per_rxd_space;
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci	ring->rxd_priv_size =
28438c2ecf20Sopenharmony_ci		((ring->rxd_priv_size + VXGE_CACHE_LINE_SIZE - 1) /
28448c2ecf20Sopenharmony_ci		VXGE_CACHE_LINE_SIZE) * VXGE_CACHE_LINE_SIZE;
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	/* how many RxDs can fit into one block. Depends on configured
28478c2ecf20Sopenharmony_ci	 * buffer_mode. */
28488c2ecf20Sopenharmony_ci	ring->rxds_per_block =
28498c2ecf20Sopenharmony_ci		vxge_hw_ring_rxds_per_block_get(config->buffer_mode);
28508c2ecf20Sopenharmony_ci
28518c2ecf20Sopenharmony_ci	/* calculate actual RxD block private size */
28528c2ecf20Sopenharmony_ci	ring->rxdblock_priv_size = ring->rxd_priv_size * ring->rxds_per_block;
28538c2ecf20Sopenharmony_ci	ring->mempool = __vxge_hw_mempool_create(hldev,
28548c2ecf20Sopenharmony_ci				VXGE_HW_BLOCK_SIZE,
28558c2ecf20Sopenharmony_ci				VXGE_HW_BLOCK_SIZE,
28568c2ecf20Sopenharmony_ci				ring->rxdblock_priv_size,
28578c2ecf20Sopenharmony_ci				ring->config->ring_blocks,
28588c2ecf20Sopenharmony_ci				ring->config->ring_blocks,
28598c2ecf20Sopenharmony_ci				&ring_mp_callback,
28608c2ecf20Sopenharmony_ci				ring);
28618c2ecf20Sopenharmony_ci	if (ring->mempool == NULL) {
28628c2ecf20Sopenharmony_ci		__vxge_hw_ring_delete(vp);
28638c2ecf20Sopenharmony_ci		return VXGE_HW_ERR_OUT_OF_MEMORY;
28648c2ecf20Sopenharmony_ci	}
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ci	status = __vxge_hw_channel_initialize(&ring->channel);
28678c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
28688c2ecf20Sopenharmony_ci		__vxge_hw_ring_delete(vp);
28698c2ecf20Sopenharmony_ci		goto exit;
28708c2ecf20Sopenharmony_ci	}
28718c2ecf20Sopenharmony_ci
28728c2ecf20Sopenharmony_ci	/* Note:
28738c2ecf20Sopenharmony_ci	 * Specifying rxd_init callback means two things:
28748c2ecf20Sopenharmony_ci	 * 1) rxds need to be initialized by driver at channel-open time;
28758c2ecf20Sopenharmony_ci	 * 2) rxds need to be posted at channel-open time
28768c2ecf20Sopenharmony_ci	 *    (that's what the initial_replenish() below does)
28778c2ecf20Sopenharmony_ci	 * Currently we don't have a case when the 1) is done without the 2).
28788c2ecf20Sopenharmony_ci	 */
28798c2ecf20Sopenharmony_ci	if (ring->rxd_init) {
28808c2ecf20Sopenharmony_ci		status = vxge_hw_ring_replenish(ring);
28818c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK) {
28828c2ecf20Sopenharmony_ci			__vxge_hw_ring_delete(vp);
28838c2ecf20Sopenharmony_ci			goto exit;
28848c2ecf20Sopenharmony_ci		}
28858c2ecf20Sopenharmony_ci	}
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	/* initial replenish will increment the counter in its post() routine,
28888c2ecf20Sopenharmony_ci	 * we have to reset it */
28898c2ecf20Sopenharmony_ci	ring->stats->common_stats.usage_cnt = 0;
28908c2ecf20Sopenharmony_ciexit:
28918c2ecf20Sopenharmony_ci	return status;
28928c2ecf20Sopenharmony_ci}
28938c2ecf20Sopenharmony_ci
28948c2ecf20Sopenharmony_ci/*
28958c2ecf20Sopenharmony_ci * vxge_hw_device_config_default_get - Initialize device config with defaults.
28968c2ecf20Sopenharmony_ci * Initialize Titan device config with default values.
28978c2ecf20Sopenharmony_ci */
28988c2ecf20Sopenharmony_cienum vxge_hw_status
28998c2ecf20Sopenharmony_civxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config)
29008c2ecf20Sopenharmony_ci{
29018c2ecf20Sopenharmony_ci	u32 i;
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci	device_config->dma_blockpool_initial =
29048c2ecf20Sopenharmony_ci					VXGE_HW_INITIAL_DMA_BLOCK_POOL_SIZE;
29058c2ecf20Sopenharmony_ci	device_config->dma_blockpool_max = VXGE_HW_MAX_DMA_BLOCK_POOL_SIZE;
29068c2ecf20Sopenharmony_ci	device_config->intr_mode = VXGE_HW_INTR_MODE_DEF;
29078c2ecf20Sopenharmony_ci	device_config->rth_en = VXGE_HW_RTH_DEFAULT;
29088c2ecf20Sopenharmony_ci	device_config->rth_it_type = VXGE_HW_RTH_IT_TYPE_DEFAULT;
29098c2ecf20Sopenharmony_ci	device_config->device_poll_millis =  VXGE_HW_DEF_DEVICE_POLL_MILLIS;
29108c2ecf20Sopenharmony_ci	device_config->rts_mac_en =  VXGE_HW_RTS_MAC_DEFAULT;
29118c2ecf20Sopenharmony_ci
29128c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
29138c2ecf20Sopenharmony_ci		device_config->vp_config[i].vp_id = i;
29148c2ecf20Sopenharmony_ci
29158c2ecf20Sopenharmony_ci		device_config->vp_config[i].min_bandwidth =
29168c2ecf20Sopenharmony_ci				VXGE_HW_VPATH_BANDWIDTH_DEFAULT;
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci		device_config->vp_config[i].ring.enable = VXGE_HW_RING_DEFAULT;
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_ci		device_config->vp_config[i].ring.ring_blocks =
29218c2ecf20Sopenharmony_ci				VXGE_HW_DEF_RING_BLOCKS;
29228c2ecf20Sopenharmony_ci
29238c2ecf20Sopenharmony_ci		device_config->vp_config[i].ring.buffer_mode =
29248c2ecf20Sopenharmony_ci				VXGE_HW_RING_RXD_BUFFER_MODE_DEFAULT;
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci		device_config->vp_config[i].ring.scatter_mode =
29278c2ecf20Sopenharmony_ci				VXGE_HW_RING_SCATTER_MODE_USE_FLASH_DEFAULT;
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ci		device_config->vp_config[i].ring.rxds_limit =
29308c2ecf20Sopenharmony_ci				VXGE_HW_DEF_RING_RXDS_LIMIT;
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.enable = VXGE_HW_FIFO_ENABLE;
29338c2ecf20Sopenharmony_ci
29348c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.fifo_blocks =
29358c2ecf20Sopenharmony_ci				VXGE_HW_MIN_FIFO_BLOCKS;
29368c2ecf20Sopenharmony_ci
29378c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.max_frags =
29388c2ecf20Sopenharmony_ci				VXGE_HW_MAX_FIFO_FRAGS;
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.memblock_size =
29418c2ecf20Sopenharmony_ci				VXGE_HW_DEF_FIFO_MEMBLOCK_SIZE;
29428c2ecf20Sopenharmony_ci
29438c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.alignment_size =
29448c2ecf20Sopenharmony_ci				VXGE_HW_DEF_FIFO_ALIGNMENT_SIZE;
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.intr =
29478c2ecf20Sopenharmony_ci				VXGE_HW_FIFO_QUEUE_INTR_DEFAULT;
29488c2ecf20Sopenharmony_ci
29498c2ecf20Sopenharmony_ci		device_config->vp_config[i].fifo.no_snoop_bits =
29508c2ecf20Sopenharmony_ci				VXGE_HW_FIFO_NO_SNOOP_DEFAULT;
29518c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.intr_enable =
29528c2ecf20Sopenharmony_ci				VXGE_HW_TIM_INTR_DEFAULT;
29538c2ecf20Sopenharmony_ci
29548c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.btimer_val =
29558c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29568c2ecf20Sopenharmony_ci
29578c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.timer_ac_en =
29588c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29598c2ecf20Sopenharmony_ci
29608c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.timer_ci_en =
29618c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29628c2ecf20Sopenharmony_ci
29638c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.timer_ri_en =
29648c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.rtimer_val =
29678c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.util_sel =
29708c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29718c2ecf20Sopenharmony_ci
29728c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.ltimer_val =
29738c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.urange_a =
29768c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.uec_a =
29798c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29808c2ecf20Sopenharmony_ci
29818c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.urange_b =
29828c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.uec_b =
29858c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29868c2ecf20Sopenharmony_ci
29878c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.urange_c =
29888c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.uec_c =
29918c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_ci		device_config->vp_config[i].tti.uec_d =
29948c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
29958c2ecf20Sopenharmony_ci
29968c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.intr_enable =
29978c2ecf20Sopenharmony_ci				VXGE_HW_TIM_INTR_DEFAULT;
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.btimer_val =
30008c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.timer_ac_en =
30038c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30048c2ecf20Sopenharmony_ci
30058c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.timer_ci_en =
30068c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.timer_ri_en =
30098c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.rtimer_val =
30128c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.util_sel =
30158c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30168c2ecf20Sopenharmony_ci
30178c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.ltimer_val =
30188c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.urange_a =
30218c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.uec_a =
30248c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30258c2ecf20Sopenharmony_ci
30268c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.urange_b =
30278c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30288c2ecf20Sopenharmony_ci
30298c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.uec_b =
30308c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30318c2ecf20Sopenharmony_ci
30328c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.urange_c =
30338c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.uec_c =
30368c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30378c2ecf20Sopenharmony_ci
30388c2ecf20Sopenharmony_ci		device_config->vp_config[i].rti.uec_d =
30398c2ecf20Sopenharmony_ci				VXGE_HW_USE_FLASH_DEFAULT;
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci		device_config->vp_config[i].mtu =
30428c2ecf20Sopenharmony_ci				VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU;
30438c2ecf20Sopenharmony_ci
30448c2ecf20Sopenharmony_ci		device_config->vp_config[i].rpa_strip_vlan_tag =
30458c2ecf20Sopenharmony_ci			VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT;
30468c2ecf20Sopenharmony_ci	}
30478c2ecf20Sopenharmony_ci
30488c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
30498c2ecf20Sopenharmony_ci}
30508c2ecf20Sopenharmony_ci
30518c2ecf20Sopenharmony_ci/*
30528c2ecf20Sopenharmony_ci * __vxge_hw_vpath_swapper_set - Set the swapper bits for the vpath.
30538c2ecf20Sopenharmony_ci * Set the swapper bits appropriately for the vpath.
30548c2ecf20Sopenharmony_ci */
30558c2ecf20Sopenharmony_cistatic enum vxge_hw_status
30568c2ecf20Sopenharmony_ci__vxge_hw_vpath_swapper_set(struct vxge_hw_vpath_reg __iomem *vpath_reg)
30578c2ecf20Sopenharmony_ci{
30588c2ecf20Sopenharmony_ci#ifndef __BIG_ENDIAN
30598c2ecf20Sopenharmony_ci	u64 val64;
30608c2ecf20Sopenharmony_ci
30618c2ecf20Sopenharmony_ci	val64 = readq(&vpath_reg->vpath_general_cfg1);
30628c2ecf20Sopenharmony_ci	wmb();
30638c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_VPATH_GENERAL_CFG1_CTL_BYTE_SWAPEN;
30648c2ecf20Sopenharmony_ci	writeq(val64, &vpath_reg->vpath_general_cfg1);
30658c2ecf20Sopenharmony_ci	wmb();
30668c2ecf20Sopenharmony_ci#endif
30678c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
30688c2ecf20Sopenharmony_ci}
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci/*
30718c2ecf20Sopenharmony_ci * __vxge_hw_kdfc_swapper_set - Set the swapper bits for the kdfc.
30728c2ecf20Sopenharmony_ci * Set the swapper bits appropriately for the vpath.
30738c2ecf20Sopenharmony_ci */
30748c2ecf20Sopenharmony_cistatic enum vxge_hw_status
30758c2ecf20Sopenharmony_ci__vxge_hw_kdfc_swapper_set(struct vxge_hw_legacy_reg __iomem *legacy_reg,
30768c2ecf20Sopenharmony_ci			   struct vxge_hw_vpath_reg __iomem *vpath_reg)
30778c2ecf20Sopenharmony_ci{
30788c2ecf20Sopenharmony_ci	u64 val64;
30798c2ecf20Sopenharmony_ci
30808c2ecf20Sopenharmony_ci	val64 = readq(&legacy_reg->pifm_wr_swap_en);
30818c2ecf20Sopenharmony_ci
30828c2ecf20Sopenharmony_ci	if (val64 == VXGE_HW_SWAPPER_WRITE_BYTE_SWAP_ENABLE) {
30838c2ecf20Sopenharmony_ci		val64 = readq(&vpath_reg->kdfcctl_cfg0);
30848c2ecf20Sopenharmony_ci		wmb();
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO0	|
30878c2ecf20Sopenharmony_ci			VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO1	|
30888c2ecf20Sopenharmony_ci			VXGE_HW_KDFCCTL_CFG0_BYTE_SWAPEN_FIFO2;
30898c2ecf20Sopenharmony_ci
30908c2ecf20Sopenharmony_ci		writeq(val64, &vpath_reg->kdfcctl_cfg0);
30918c2ecf20Sopenharmony_ci		wmb();
30928c2ecf20Sopenharmony_ci	}
30938c2ecf20Sopenharmony_ci
30948c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
30958c2ecf20Sopenharmony_ci}
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ci/*
30988c2ecf20Sopenharmony_ci * vxge_hw_mgmt_reg_read - Read Titan register.
30998c2ecf20Sopenharmony_ci */
31008c2ecf20Sopenharmony_cienum vxge_hw_status
31018c2ecf20Sopenharmony_civxge_hw_mgmt_reg_read(struct __vxge_hw_device *hldev,
31028c2ecf20Sopenharmony_ci		      enum vxge_hw_mgmt_reg_type type,
31038c2ecf20Sopenharmony_ci		      u32 index, u32 offset, u64 *value)
31048c2ecf20Sopenharmony_ci{
31058c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
31068c2ecf20Sopenharmony_ci
31078c2ecf20Sopenharmony_ci	if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
31088c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_DEVICE;
31098c2ecf20Sopenharmony_ci		goto exit;
31108c2ecf20Sopenharmony_ci	}
31118c2ecf20Sopenharmony_ci
31128c2ecf20Sopenharmony_ci	switch (type) {
31138c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_legacy:
31148c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_legacy_reg) - 8) {
31158c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31168c2ecf20Sopenharmony_ci			break;
31178c2ecf20Sopenharmony_ci		}
31188c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->legacy_reg + offset);
31198c2ecf20Sopenharmony_ci		break;
31208c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_toc:
31218c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_toc_reg) - 8) {
31228c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31238c2ecf20Sopenharmony_ci			break;
31248c2ecf20Sopenharmony_ci		}
31258c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->toc_reg + offset);
31268c2ecf20Sopenharmony_ci		break;
31278c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_common:
31288c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_common_reg) - 8) {
31298c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31308c2ecf20Sopenharmony_ci			break;
31318c2ecf20Sopenharmony_ci		}
31328c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->common_reg + offset);
31338c2ecf20Sopenharmony_ci		break;
31348c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_mrpcim:
31358c2ecf20Sopenharmony_ci		if (!(hldev->access_rights &
31368c2ecf20Sopenharmony_ci			VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) {
31378c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_PRIVILEGED_OPERATION;
31388c2ecf20Sopenharmony_ci			break;
31398c2ecf20Sopenharmony_ci		}
31408c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_mrpcim_reg) - 8) {
31418c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31428c2ecf20Sopenharmony_ci			break;
31438c2ecf20Sopenharmony_ci		}
31448c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->mrpcim_reg + offset);
31458c2ecf20Sopenharmony_ci		break;
31468c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_srpcim:
31478c2ecf20Sopenharmony_ci		if (!(hldev->access_rights &
31488c2ecf20Sopenharmony_ci			VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM)) {
31498c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_PRIVILEGED_OPERATION;
31508c2ecf20Sopenharmony_ci			break;
31518c2ecf20Sopenharmony_ci		}
31528c2ecf20Sopenharmony_ci		if (index > VXGE_HW_TITAN_SRPCIM_REG_SPACES - 1) {
31538c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
31548c2ecf20Sopenharmony_ci			break;
31558c2ecf20Sopenharmony_ci		}
31568c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_srpcim_reg) - 8) {
31578c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31588c2ecf20Sopenharmony_ci			break;
31598c2ecf20Sopenharmony_ci		}
31608c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->srpcim_reg[index] +
31618c2ecf20Sopenharmony_ci				offset);
31628c2ecf20Sopenharmony_ci		break;
31638c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_vpmgmt:
31648c2ecf20Sopenharmony_ci		if ((index > VXGE_HW_TITAN_VPMGMT_REG_SPACES - 1) ||
31658c2ecf20Sopenharmony_ci			(!(hldev->vpath_assignments & vxge_mBIT(index)))) {
31668c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
31678c2ecf20Sopenharmony_ci			break;
31688c2ecf20Sopenharmony_ci		}
31698c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_vpmgmt_reg) - 8) {
31708c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31718c2ecf20Sopenharmony_ci			break;
31728c2ecf20Sopenharmony_ci		}
31738c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->vpmgmt_reg[index] +
31748c2ecf20Sopenharmony_ci				offset);
31758c2ecf20Sopenharmony_ci		break;
31768c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_vpath:
31778c2ecf20Sopenharmony_ci		if ((index > VXGE_HW_TITAN_VPATH_REG_SPACES - 1) ||
31788c2ecf20Sopenharmony_ci			(!(hldev->vpath_assignments & vxge_mBIT(index)))) {
31798c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
31808c2ecf20Sopenharmony_ci			break;
31818c2ecf20Sopenharmony_ci		}
31828c2ecf20Sopenharmony_ci		if (index > VXGE_HW_TITAN_VPATH_REG_SPACES - 1) {
31838c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
31848c2ecf20Sopenharmony_ci			break;
31858c2ecf20Sopenharmony_ci		}
31868c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_vpath_reg) - 8) {
31878c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
31888c2ecf20Sopenharmony_ci			break;
31898c2ecf20Sopenharmony_ci		}
31908c2ecf20Sopenharmony_ci		*value = readq((void __iomem *)hldev->vpath_reg[index] +
31918c2ecf20Sopenharmony_ci				offset);
31928c2ecf20Sopenharmony_ci		break;
31938c2ecf20Sopenharmony_ci	default:
31948c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_TYPE;
31958c2ecf20Sopenharmony_ci		break;
31968c2ecf20Sopenharmony_ci	}
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ciexit:
31998c2ecf20Sopenharmony_ci	return status;
32008c2ecf20Sopenharmony_ci}
32018c2ecf20Sopenharmony_ci
32028c2ecf20Sopenharmony_ci/*
32038c2ecf20Sopenharmony_ci * vxge_hw_vpath_strip_fcs_check - Check for FCS strip.
32048c2ecf20Sopenharmony_ci */
32058c2ecf20Sopenharmony_cienum vxge_hw_status
32068c2ecf20Sopenharmony_civxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask)
32078c2ecf20Sopenharmony_ci{
32088c2ecf20Sopenharmony_ci	struct vxge_hw_vpmgmt_reg       __iomem *vpmgmt_reg;
32098c2ecf20Sopenharmony_ci	int i = 0, j = 0;
32108c2ecf20Sopenharmony_ci
32118c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
32128c2ecf20Sopenharmony_ci		if (!((vpath_mask) & vxge_mBIT(i)))
32138c2ecf20Sopenharmony_ci			continue;
32148c2ecf20Sopenharmony_ci		vpmgmt_reg = hldev->vpmgmt_reg[i];
32158c2ecf20Sopenharmony_ci		for (j = 0; j < VXGE_HW_MAC_MAX_MAC_PORT_ID; j++) {
32168c2ecf20Sopenharmony_ci			if (readq(&vpmgmt_reg->rxmac_cfg0_port_vpmgmt_clone[j])
32178c2ecf20Sopenharmony_ci			& VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_STRIP_FCS)
32188c2ecf20Sopenharmony_ci				return VXGE_HW_FAIL;
32198c2ecf20Sopenharmony_ci		}
32208c2ecf20Sopenharmony_ci	}
32218c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
32228c2ecf20Sopenharmony_ci}
32238c2ecf20Sopenharmony_ci/*
32248c2ecf20Sopenharmony_ci * vxge_hw_mgmt_reg_Write - Write Titan register.
32258c2ecf20Sopenharmony_ci */
32268c2ecf20Sopenharmony_cienum vxge_hw_status
32278c2ecf20Sopenharmony_civxge_hw_mgmt_reg_write(struct __vxge_hw_device *hldev,
32288c2ecf20Sopenharmony_ci		      enum vxge_hw_mgmt_reg_type type,
32298c2ecf20Sopenharmony_ci		      u32 index, u32 offset, u64 value)
32308c2ecf20Sopenharmony_ci{
32318c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci	if ((hldev == NULL) || (hldev->magic != VXGE_HW_DEVICE_MAGIC)) {
32348c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_DEVICE;
32358c2ecf20Sopenharmony_ci		goto exit;
32368c2ecf20Sopenharmony_ci	}
32378c2ecf20Sopenharmony_ci
32388c2ecf20Sopenharmony_ci	switch (type) {
32398c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_legacy:
32408c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_legacy_reg) - 8) {
32418c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
32428c2ecf20Sopenharmony_ci			break;
32438c2ecf20Sopenharmony_ci		}
32448c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->legacy_reg + offset);
32458c2ecf20Sopenharmony_ci		break;
32468c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_toc:
32478c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_toc_reg) - 8) {
32488c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
32498c2ecf20Sopenharmony_ci			break;
32508c2ecf20Sopenharmony_ci		}
32518c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->toc_reg + offset);
32528c2ecf20Sopenharmony_ci		break;
32538c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_common:
32548c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_common_reg) - 8) {
32558c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
32568c2ecf20Sopenharmony_ci			break;
32578c2ecf20Sopenharmony_ci		}
32588c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->common_reg + offset);
32598c2ecf20Sopenharmony_ci		break;
32608c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_mrpcim:
32618c2ecf20Sopenharmony_ci		if (!(hldev->access_rights &
32628c2ecf20Sopenharmony_ci			VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)) {
32638c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_PRIVILEGED_OPERATION;
32648c2ecf20Sopenharmony_ci			break;
32658c2ecf20Sopenharmony_ci		}
32668c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_mrpcim_reg) - 8) {
32678c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
32688c2ecf20Sopenharmony_ci			break;
32698c2ecf20Sopenharmony_ci		}
32708c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->mrpcim_reg + offset);
32718c2ecf20Sopenharmony_ci		break;
32728c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_srpcim:
32738c2ecf20Sopenharmony_ci		if (!(hldev->access_rights &
32748c2ecf20Sopenharmony_ci			VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM)) {
32758c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_PRIVILEGED_OPERATION;
32768c2ecf20Sopenharmony_ci			break;
32778c2ecf20Sopenharmony_ci		}
32788c2ecf20Sopenharmony_ci		if (index > VXGE_HW_TITAN_SRPCIM_REG_SPACES - 1) {
32798c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
32808c2ecf20Sopenharmony_ci			break;
32818c2ecf20Sopenharmony_ci		}
32828c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_srpcim_reg) - 8) {
32838c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
32848c2ecf20Sopenharmony_ci			break;
32858c2ecf20Sopenharmony_ci		}
32868c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->srpcim_reg[index] +
32878c2ecf20Sopenharmony_ci			offset);
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci		break;
32908c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_vpmgmt:
32918c2ecf20Sopenharmony_ci		if ((index > VXGE_HW_TITAN_VPMGMT_REG_SPACES - 1) ||
32928c2ecf20Sopenharmony_ci			(!(hldev->vpath_assignments & vxge_mBIT(index)))) {
32938c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
32948c2ecf20Sopenharmony_ci			break;
32958c2ecf20Sopenharmony_ci		}
32968c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_vpmgmt_reg) - 8) {
32978c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
32988c2ecf20Sopenharmony_ci			break;
32998c2ecf20Sopenharmony_ci		}
33008c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->vpmgmt_reg[index] +
33018c2ecf20Sopenharmony_ci			offset);
33028c2ecf20Sopenharmony_ci		break;
33038c2ecf20Sopenharmony_ci	case vxge_hw_mgmt_reg_type_vpath:
33048c2ecf20Sopenharmony_ci		if ((index > VXGE_HW_TITAN_VPATH_REG_SPACES-1) ||
33058c2ecf20Sopenharmony_ci			(!(hldev->vpath_assignments & vxge_mBIT(index)))) {
33068c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_INDEX;
33078c2ecf20Sopenharmony_ci			break;
33088c2ecf20Sopenharmony_ci		}
33098c2ecf20Sopenharmony_ci		if (offset > sizeof(struct vxge_hw_vpath_reg) - 8) {
33108c2ecf20Sopenharmony_ci			status = VXGE_HW_ERR_INVALID_OFFSET;
33118c2ecf20Sopenharmony_ci			break;
33128c2ecf20Sopenharmony_ci		}
33138c2ecf20Sopenharmony_ci		writeq(value, (void __iomem *)hldev->vpath_reg[index] +
33148c2ecf20Sopenharmony_ci			offset);
33158c2ecf20Sopenharmony_ci		break;
33168c2ecf20Sopenharmony_ci	default:
33178c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_TYPE;
33188c2ecf20Sopenharmony_ci		break;
33198c2ecf20Sopenharmony_ci	}
33208c2ecf20Sopenharmony_ciexit:
33218c2ecf20Sopenharmony_ci	return status;
33228c2ecf20Sopenharmony_ci}
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci/*
33258c2ecf20Sopenharmony_ci * __vxge_hw_fifo_abort - Returns the TxD
33268c2ecf20Sopenharmony_ci * This function terminates the TxDs of fifo
33278c2ecf20Sopenharmony_ci */
33288c2ecf20Sopenharmony_cistatic enum vxge_hw_status __vxge_hw_fifo_abort(struct __vxge_hw_fifo *fifo)
33298c2ecf20Sopenharmony_ci{
33308c2ecf20Sopenharmony_ci	void *txdlh;
33318c2ecf20Sopenharmony_ci
33328c2ecf20Sopenharmony_ci	for (;;) {
33338c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_try_complete(&fifo->channel, &txdlh);
33348c2ecf20Sopenharmony_ci
33358c2ecf20Sopenharmony_ci		if (txdlh == NULL)
33368c2ecf20Sopenharmony_ci			break;
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_complete(&fifo->channel);
33398c2ecf20Sopenharmony_ci
33408c2ecf20Sopenharmony_ci		if (fifo->txdl_term) {
33418c2ecf20Sopenharmony_ci			fifo->txdl_term(txdlh,
33428c2ecf20Sopenharmony_ci			VXGE_HW_TXDL_STATE_POSTED,
33438c2ecf20Sopenharmony_ci			fifo->channel.userdata);
33448c2ecf20Sopenharmony_ci		}
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci		vxge_hw_channel_dtr_free(&fifo->channel, txdlh);
33478c2ecf20Sopenharmony_ci	}
33488c2ecf20Sopenharmony_ci
33498c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
33508c2ecf20Sopenharmony_ci}
33518c2ecf20Sopenharmony_ci
33528c2ecf20Sopenharmony_ci/*
33538c2ecf20Sopenharmony_ci * __vxge_hw_fifo_reset - Resets the fifo
33548c2ecf20Sopenharmony_ci * This function resets the fifo during vpath reset operation
33558c2ecf20Sopenharmony_ci */
33568c2ecf20Sopenharmony_cistatic enum vxge_hw_status __vxge_hw_fifo_reset(struct __vxge_hw_fifo *fifo)
33578c2ecf20Sopenharmony_ci{
33588c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_ci	__vxge_hw_fifo_abort(fifo);
33618c2ecf20Sopenharmony_ci	status = __vxge_hw_channel_reset(&fifo->channel);
33628c2ecf20Sopenharmony_ci
33638c2ecf20Sopenharmony_ci	return status;
33648c2ecf20Sopenharmony_ci}
33658c2ecf20Sopenharmony_ci
33668c2ecf20Sopenharmony_ci/*
33678c2ecf20Sopenharmony_ci * __vxge_hw_fifo_delete - Removes the FIFO
33688c2ecf20Sopenharmony_ci * This function freeup the memory pool and removes the FIFO
33698c2ecf20Sopenharmony_ci */
33708c2ecf20Sopenharmony_cistatic enum vxge_hw_status
33718c2ecf20Sopenharmony_ci__vxge_hw_fifo_delete(struct __vxge_hw_vpath_handle *vp)
33728c2ecf20Sopenharmony_ci{
33738c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo *fifo = vp->vpath->fifoh;
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	__vxge_hw_fifo_abort(fifo);
33768c2ecf20Sopenharmony_ci
33778c2ecf20Sopenharmony_ci	if (fifo->mempool)
33788c2ecf20Sopenharmony_ci		__vxge_hw_mempool_destroy(fifo->mempool);
33798c2ecf20Sopenharmony_ci
33808c2ecf20Sopenharmony_ci	vp->vpath->fifoh = NULL;
33818c2ecf20Sopenharmony_ci
33828c2ecf20Sopenharmony_ci	__vxge_hw_channel_free(&fifo->channel);
33838c2ecf20Sopenharmony_ci
33848c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
33858c2ecf20Sopenharmony_ci}
33868c2ecf20Sopenharmony_ci
33878c2ecf20Sopenharmony_ci/*
33888c2ecf20Sopenharmony_ci * __vxge_hw_fifo_mempool_item_alloc - Allocate List blocks for TxD
33898c2ecf20Sopenharmony_ci * list callback
33908c2ecf20Sopenharmony_ci * This function is callback passed to __vxge_hw_mempool_create to create memory
33918c2ecf20Sopenharmony_ci * pool for TxD list
33928c2ecf20Sopenharmony_ci */
33938c2ecf20Sopenharmony_cistatic void
33948c2ecf20Sopenharmony_ci__vxge_hw_fifo_mempool_item_alloc(
33958c2ecf20Sopenharmony_ci	struct vxge_hw_mempool *mempoolh,
33968c2ecf20Sopenharmony_ci	u32 memblock_index, struct vxge_hw_mempool_dma *dma_object,
33978c2ecf20Sopenharmony_ci	u32 index, u32 is_last)
33988c2ecf20Sopenharmony_ci{
33998c2ecf20Sopenharmony_ci	u32 memblock_item_idx;
34008c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo_txdl_priv *txdl_priv;
34018c2ecf20Sopenharmony_ci	struct vxge_hw_fifo_txd *txdp =
34028c2ecf20Sopenharmony_ci		(struct vxge_hw_fifo_txd *)mempoolh->items_arr[index];
34038c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo *fifo =
34048c2ecf20Sopenharmony_ci			(struct __vxge_hw_fifo *)mempoolh->userdata;
34058c2ecf20Sopenharmony_ci	void *memblock = mempoolh->memblocks_arr[memblock_index];
34068c2ecf20Sopenharmony_ci
34078c2ecf20Sopenharmony_ci	vxge_assert(txdp);
34088c2ecf20Sopenharmony_ci
34098c2ecf20Sopenharmony_ci	txdp->host_control = (u64) (size_t)
34108c2ecf20Sopenharmony_ci	__vxge_hw_mempool_item_priv(mempoolh, memblock_index, txdp,
34118c2ecf20Sopenharmony_ci					&memblock_item_idx);
34128c2ecf20Sopenharmony_ci
34138c2ecf20Sopenharmony_ci	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdp);
34148c2ecf20Sopenharmony_ci
34158c2ecf20Sopenharmony_ci	vxge_assert(txdl_priv);
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	fifo->channel.reserve_arr[fifo->channel.reserve_ptr - 1 - index] = txdp;
34188c2ecf20Sopenharmony_ci
34198c2ecf20Sopenharmony_ci	/* pre-format HW's TxDL's private */
34208c2ecf20Sopenharmony_ci	txdl_priv->dma_offset = (char *)txdp - (char *)memblock;
34218c2ecf20Sopenharmony_ci	txdl_priv->dma_addr = dma_object->addr + txdl_priv->dma_offset;
34228c2ecf20Sopenharmony_ci	txdl_priv->dma_handle = dma_object->handle;
34238c2ecf20Sopenharmony_ci	txdl_priv->memblock   = memblock;
34248c2ecf20Sopenharmony_ci	txdl_priv->first_txdp = txdp;
34258c2ecf20Sopenharmony_ci	txdl_priv->next_txdl_priv = NULL;
34268c2ecf20Sopenharmony_ci	txdl_priv->alloc_frags = 0;
34278c2ecf20Sopenharmony_ci}
34288c2ecf20Sopenharmony_ci
34298c2ecf20Sopenharmony_ci/*
34308c2ecf20Sopenharmony_ci * __vxge_hw_fifo_create - Create a FIFO
34318c2ecf20Sopenharmony_ci * This function creates FIFO and initializes it.
34328c2ecf20Sopenharmony_ci */
34338c2ecf20Sopenharmony_cistatic enum vxge_hw_status
34348c2ecf20Sopenharmony_ci__vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp,
34358c2ecf20Sopenharmony_ci		      struct vxge_hw_fifo_attr *attr)
34368c2ecf20Sopenharmony_ci{
34378c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
34388c2ecf20Sopenharmony_ci	struct __vxge_hw_fifo *fifo;
34398c2ecf20Sopenharmony_ci	struct vxge_hw_fifo_config *config;
34408c2ecf20Sopenharmony_ci	u32 txdl_size, txdl_per_memblock;
34418c2ecf20Sopenharmony_ci	struct vxge_hw_mempool_cbs fifo_mp_callback;
34428c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
34438c2ecf20Sopenharmony_ci
34448c2ecf20Sopenharmony_ci	if ((vp == NULL) || (attr == NULL)) {
34458c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
34468c2ecf20Sopenharmony_ci		goto exit;
34478c2ecf20Sopenharmony_ci	}
34488c2ecf20Sopenharmony_ci	vpath = vp->vpath;
34498c2ecf20Sopenharmony_ci	config = &vpath->hldev->config.vp_config[vpath->vp_id].fifo;
34508c2ecf20Sopenharmony_ci
34518c2ecf20Sopenharmony_ci	txdl_size = config->max_frags * sizeof(struct vxge_hw_fifo_txd);
34528c2ecf20Sopenharmony_ci
34538c2ecf20Sopenharmony_ci	txdl_per_memblock = config->memblock_size / txdl_size;
34548c2ecf20Sopenharmony_ci
34558c2ecf20Sopenharmony_ci	fifo = (struct __vxge_hw_fifo *)__vxge_hw_channel_allocate(vp,
34568c2ecf20Sopenharmony_ci					VXGE_HW_CHANNEL_TYPE_FIFO,
34578c2ecf20Sopenharmony_ci					config->fifo_blocks * txdl_per_memblock,
34588c2ecf20Sopenharmony_ci					attr->per_txdl_space, attr->userdata);
34598c2ecf20Sopenharmony_ci
34608c2ecf20Sopenharmony_ci	if (fifo == NULL) {
34618c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
34628c2ecf20Sopenharmony_ci		goto exit;
34638c2ecf20Sopenharmony_ci	}
34648c2ecf20Sopenharmony_ci
34658c2ecf20Sopenharmony_ci	vpath->fifoh = fifo;
34668c2ecf20Sopenharmony_ci	fifo->nofl_db = vpath->nofl_db;
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	fifo->vp_id = vpath->vp_id;
34698c2ecf20Sopenharmony_ci	fifo->vp_reg = vpath->vp_reg;
34708c2ecf20Sopenharmony_ci	fifo->stats = &vpath->sw_stats->fifo_stats;
34718c2ecf20Sopenharmony_ci
34728c2ecf20Sopenharmony_ci	fifo->config = config;
34738c2ecf20Sopenharmony_ci
34748c2ecf20Sopenharmony_ci	/* apply "interrupts per txdl" attribute */
34758c2ecf20Sopenharmony_ci	fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_UTILZ;
34768c2ecf20Sopenharmony_ci	fifo->tim_tti_cfg1_saved = vpath->tim_tti_cfg1_saved;
34778c2ecf20Sopenharmony_ci	fifo->tim_tti_cfg3_saved = vpath->tim_tti_cfg3_saved;
34788c2ecf20Sopenharmony_ci
34798c2ecf20Sopenharmony_ci	if (fifo->config->intr)
34808c2ecf20Sopenharmony_ci		fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_PER_LIST;
34818c2ecf20Sopenharmony_ci
34828c2ecf20Sopenharmony_ci	fifo->no_snoop_bits = config->no_snoop_bits;
34838c2ecf20Sopenharmony_ci
34848c2ecf20Sopenharmony_ci	/*
34858c2ecf20Sopenharmony_ci	 * FIFO memory management strategy:
34868c2ecf20Sopenharmony_ci	 *
34878c2ecf20Sopenharmony_ci	 * TxDL split into three independent parts:
34888c2ecf20Sopenharmony_ci	 *	- set of TxD's
34898c2ecf20Sopenharmony_ci	 *	- TxD HW private part
34908c2ecf20Sopenharmony_ci	 *	- driver private part
34918c2ecf20Sopenharmony_ci	 *
34928c2ecf20Sopenharmony_ci	 * Adaptative memory allocation used. i.e. Memory allocated on
34938c2ecf20Sopenharmony_ci	 * demand with the size which will fit into one memory block.
34948c2ecf20Sopenharmony_ci	 * One memory block may contain more than one TxDL.
34958c2ecf20Sopenharmony_ci	 *
34968c2ecf20Sopenharmony_ci	 * During "reserve" operations more memory can be allocated on demand
34978c2ecf20Sopenharmony_ci	 * for example due to FIFO full condition.
34988c2ecf20Sopenharmony_ci	 *
34998c2ecf20Sopenharmony_ci	 * Pool of memory memblocks never shrinks except in __vxge_hw_fifo_close
35008c2ecf20Sopenharmony_ci	 * routine which will essentially stop the channel and free resources.
35018c2ecf20Sopenharmony_ci	 */
35028c2ecf20Sopenharmony_ci
35038c2ecf20Sopenharmony_ci	/* TxDL common private size == TxDL private  +  driver private */
35048c2ecf20Sopenharmony_ci	fifo->priv_size =
35058c2ecf20Sopenharmony_ci		sizeof(struct __vxge_hw_fifo_txdl_priv) + attr->per_txdl_space;
35068c2ecf20Sopenharmony_ci	fifo->priv_size = ((fifo->priv_size  +  VXGE_CACHE_LINE_SIZE - 1) /
35078c2ecf20Sopenharmony_ci			VXGE_CACHE_LINE_SIZE) * VXGE_CACHE_LINE_SIZE;
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ci	fifo->per_txdl_space = attr->per_txdl_space;
35108c2ecf20Sopenharmony_ci
35118c2ecf20Sopenharmony_ci	/* recompute txdl size to be cacheline aligned */
35128c2ecf20Sopenharmony_ci	fifo->txdl_size = txdl_size;
35138c2ecf20Sopenharmony_ci	fifo->txdl_per_memblock = txdl_per_memblock;
35148c2ecf20Sopenharmony_ci
35158c2ecf20Sopenharmony_ci	fifo->txdl_term = attr->txdl_term;
35168c2ecf20Sopenharmony_ci	fifo->callback = attr->callback;
35178c2ecf20Sopenharmony_ci
35188c2ecf20Sopenharmony_ci	if (fifo->txdl_per_memblock == 0) {
35198c2ecf20Sopenharmony_ci		__vxge_hw_fifo_delete(vp);
35208c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_BLOCK_SIZE;
35218c2ecf20Sopenharmony_ci		goto exit;
35228c2ecf20Sopenharmony_ci	}
35238c2ecf20Sopenharmony_ci
35248c2ecf20Sopenharmony_ci	fifo_mp_callback.item_func_alloc = __vxge_hw_fifo_mempool_item_alloc;
35258c2ecf20Sopenharmony_ci
35268c2ecf20Sopenharmony_ci	fifo->mempool =
35278c2ecf20Sopenharmony_ci		__vxge_hw_mempool_create(vpath->hldev,
35288c2ecf20Sopenharmony_ci			fifo->config->memblock_size,
35298c2ecf20Sopenharmony_ci			fifo->txdl_size,
35308c2ecf20Sopenharmony_ci			fifo->priv_size,
35318c2ecf20Sopenharmony_ci			(fifo->config->fifo_blocks * fifo->txdl_per_memblock),
35328c2ecf20Sopenharmony_ci			(fifo->config->fifo_blocks * fifo->txdl_per_memblock),
35338c2ecf20Sopenharmony_ci			&fifo_mp_callback,
35348c2ecf20Sopenharmony_ci			fifo);
35358c2ecf20Sopenharmony_ci
35368c2ecf20Sopenharmony_ci	if (fifo->mempool == NULL) {
35378c2ecf20Sopenharmony_ci		__vxge_hw_fifo_delete(vp);
35388c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
35398c2ecf20Sopenharmony_ci		goto exit;
35408c2ecf20Sopenharmony_ci	}
35418c2ecf20Sopenharmony_ci
35428c2ecf20Sopenharmony_ci	status = __vxge_hw_channel_initialize(&fifo->channel);
35438c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
35448c2ecf20Sopenharmony_ci		__vxge_hw_fifo_delete(vp);
35458c2ecf20Sopenharmony_ci		goto exit;
35468c2ecf20Sopenharmony_ci	}
35478c2ecf20Sopenharmony_ci
35488c2ecf20Sopenharmony_ci	vxge_assert(fifo->channel.reserve_ptr);
35498c2ecf20Sopenharmony_ciexit:
35508c2ecf20Sopenharmony_ci	return status;
35518c2ecf20Sopenharmony_ci}
35528c2ecf20Sopenharmony_ci
35538c2ecf20Sopenharmony_ci/*
35548c2ecf20Sopenharmony_ci * __vxge_hw_vpath_pci_read - Read the content of given address
35558c2ecf20Sopenharmony_ci *                          in pci config space.
35568c2ecf20Sopenharmony_ci * Read from the vpath pci config space.
35578c2ecf20Sopenharmony_ci */
35588c2ecf20Sopenharmony_cistatic enum vxge_hw_status
35598c2ecf20Sopenharmony_ci__vxge_hw_vpath_pci_read(struct __vxge_hw_virtualpath *vpath,
35608c2ecf20Sopenharmony_ci			 u32 phy_func_0, u32 offset, u32 *val)
35618c2ecf20Sopenharmony_ci{
35628c2ecf20Sopenharmony_ci	u64 val64;
35638c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
35648c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
35658c2ecf20Sopenharmony_ci
35668c2ecf20Sopenharmony_ci	val64 =	VXGE_HW_PCI_CONFIG_ACCESS_CFG1_ADDRESS(offset);
35678c2ecf20Sopenharmony_ci
35688c2ecf20Sopenharmony_ci	if (phy_func_0)
35698c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_PCI_CONFIG_ACCESS_CFG1_SEL_FUNC0;
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->pci_config_access_cfg1);
35728c2ecf20Sopenharmony_ci	wmb();
35738c2ecf20Sopenharmony_ci	writeq(VXGE_HW_PCI_CONFIG_ACCESS_CFG2_REQ,
35748c2ecf20Sopenharmony_ci			&vp_reg->pci_config_access_cfg2);
35758c2ecf20Sopenharmony_ci	wmb();
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci	status = __vxge_hw_device_register_poll(
35788c2ecf20Sopenharmony_ci			&vp_reg->pci_config_access_cfg2,
35798c2ecf20Sopenharmony_ci			VXGE_HW_INTR_MASK_ALL, VXGE_HW_DEF_DEVICE_POLL_MILLIS);
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
35828c2ecf20Sopenharmony_ci		goto exit;
35838c2ecf20Sopenharmony_ci
35848c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->pci_config_access_status);
35858c2ecf20Sopenharmony_ci
35868c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_PCI_CONFIG_ACCESS_STATUS_ACCESS_ERR) {
35878c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
35888c2ecf20Sopenharmony_ci		*val = 0;
35898c2ecf20Sopenharmony_ci	} else
35908c2ecf20Sopenharmony_ci		*val = (u32)vxge_bVALn(val64, 32, 32);
35918c2ecf20Sopenharmony_ciexit:
35928c2ecf20Sopenharmony_ci	return status;
35938c2ecf20Sopenharmony_ci}
35948c2ecf20Sopenharmony_ci
35958c2ecf20Sopenharmony_ci/**
35968c2ecf20Sopenharmony_ci * vxge_hw_device_flick_link_led - Flick (blink) link LED.
35978c2ecf20Sopenharmony_ci * @hldev: HW device.
35988c2ecf20Sopenharmony_ci * @on_off: TRUE if flickering to be on, FALSE to be off
35998c2ecf20Sopenharmony_ci *
36008c2ecf20Sopenharmony_ci * Flicker the link LED.
36018c2ecf20Sopenharmony_ci */
36028c2ecf20Sopenharmony_cienum vxge_hw_status
36038c2ecf20Sopenharmony_civxge_hw_device_flick_link_led(struct __vxge_hw_device *hldev, u64 on_off)
36048c2ecf20Sopenharmony_ci{
36058c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
36068c2ecf20Sopenharmony_ci	u64 data0, data1 = 0, steer_ctrl = 0;
36078c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
36088c2ecf20Sopenharmony_ci
36098c2ecf20Sopenharmony_ci	if (hldev == NULL) {
36108c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_DEVICE;
36118c2ecf20Sopenharmony_ci		goto exit;
36128c2ecf20Sopenharmony_ci	}
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[hldev->first_vp_id];
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	data0 = on_off;
36178c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vpath,
36188c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LED_CONTROL,
36198c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
36208c2ecf20Sopenharmony_ci			0, &data0, &data1, &steer_ctrl);
36218c2ecf20Sopenharmony_ciexit:
36228c2ecf20Sopenharmony_ci	return status;
36238c2ecf20Sopenharmony_ci}
36248c2ecf20Sopenharmony_ci
36258c2ecf20Sopenharmony_ci/*
36268c2ecf20Sopenharmony_ci * __vxge_hw_vpath_rts_table_get - Get the entries from RTS access tables
36278c2ecf20Sopenharmony_ci */
36288c2ecf20Sopenharmony_cienum vxge_hw_status
36298c2ecf20Sopenharmony_ci__vxge_hw_vpath_rts_table_get(struct __vxge_hw_vpath_handle *vp,
36308c2ecf20Sopenharmony_ci			      u32 action, u32 rts_table, u32 offset,
36318c2ecf20Sopenharmony_ci			      u64 *data0, u64 *data1)
36328c2ecf20Sopenharmony_ci{
36338c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
36348c2ecf20Sopenharmony_ci	u64 steer_ctrl = 0;
36358c2ecf20Sopenharmony_ci
36368c2ecf20Sopenharmony_ci	if (vp == NULL) {
36378c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
36388c2ecf20Sopenharmony_ci		goto exit;
36398c2ecf20Sopenharmony_ci	}
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_ci	if ((rts_table ==
36428c2ecf20Sopenharmony_ci	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT) ||
36438c2ecf20Sopenharmony_ci	    (rts_table ==
36448c2ecf20Sopenharmony_ci	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT) ||
36458c2ecf20Sopenharmony_ci	    (rts_table ==
36468c2ecf20Sopenharmony_ci	     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MASK) ||
36478c2ecf20Sopenharmony_ci	    (rts_table ==
36488c2ecf20Sopenharmony_ci	     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_KEY)) {
36498c2ecf20Sopenharmony_ci		steer_ctrl = VXGE_HW_RTS_ACCESS_STEER_CTRL_TABLE_SEL;
36508c2ecf20Sopenharmony_ci	}
36518c2ecf20Sopenharmony_ci
36528c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset,
36538c2ecf20Sopenharmony_ci				      data0, data1, &steer_ctrl);
36548c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
36558c2ecf20Sopenharmony_ci		goto exit;
36568c2ecf20Sopenharmony_ci
36578c2ecf20Sopenharmony_ci	if ((rts_table != VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) &&
36588c2ecf20Sopenharmony_ci	    (rts_table !=
36598c2ecf20Sopenharmony_ci	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT))
36608c2ecf20Sopenharmony_ci		*data1 = 0;
36618c2ecf20Sopenharmony_ciexit:
36628c2ecf20Sopenharmony_ci	return status;
36638c2ecf20Sopenharmony_ci}
36648c2ecf20Sopenharmony_ci
36658c2ecf20Sopenharmony_ci/*
36668c2ecf20Sopenharmony_ci * __vxge_hw_vpath_rts_table_set - Set the entries of RTS access tables
36678c2ecf20Sopenharmony_ci */
36688c2ecf20Sopenharmony_cienum vxge_hw_status
36698c2ecf20Sopenharmony_ci__vxge_hw_vpath_rts_table_set(struct __vxge_hw_vpath_handle *vp, u32 action,
36708c2ecf20Sopenharmony_ci			      u32 rts_table, u32 offset, u64 steer_data0,
36718c2ecf20Sopenharmony_ci			      u64 steer_data1)
36728c2ecf20Sopenharmony_ci{
36738c2ecf20Sopenharmony_ci	u64 data0, data1 = 0, steer_ctrl = 0;
36748c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
36758c2ecf20Sopenharmony_ci
36768c2ecf20Sopenharmony_ci	if (vp == NULL) {
36778c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
36788c2ecf20Sopenharmony_ci		goto exit;
36798c2ecf20Sopenharmony_ci	}
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci	data0 = steer_data0;
36828c2ecf20Sopenharmony_ci
36838c2ecf20Sopenharmony_ci	if ((rts_table == VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA) ||
36848c2ecf20Sopenharmony_ci	    (rts_table ==
36858c2ecf20Sopenharmony_ci	     VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT))
36868c2ecf20Sopenharmony_ci		data1 = steer_data1;
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_fw_api(vp->vpath, action, rts_table, offset,
36898c2ecf20Sopenharmony_ci				      &data0, &data1, &steer_ctrl);
36908c2ecf20Sopenharmony_ciexit:
36918c2ecf20Sopenharmony_ci	return status;
36928c2ecf20Sopenharmony_ci}
36938c2ecf20Sopenharmony_ci
36948c2ecf20Sopenharmony_ci/*
36958c2ecf20Sopenharmony_ci * vxge_hw_vpath_rts_rth_set - Set/configure RTS hashing.
36968c2ecf20Sopenharmony_ci */
36978c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_rts_rth_set(
36988c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle *vp,
36998c2ecf20Sopenharmony_ci			enum vxge_hw_rth_algoritms algorithm,
37008c2ecf20Sopenharmony_ci			struct vxge_hw_rth_hash_types *hash_type,
37018c2ecf20Sopenharmony_ci			u16 bucket_size)
37028c2ecf20Sopenharmony_ci{
37038c2ecf20Sopenharmony_ci	u64 data0, data1;
37048c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
37058c2ecf20Sopenharmony_ci
37068c2ecf20Sopenharmony_ci	if (vp == NULL) {
37078c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
37088c2ecf20Sopenharmony_ci		goto exit;
37098c2ecf20Sopenharmony_ci	}
37108c2ecf20Sopenharmony_ci
37118c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_get(vp,
37128c2ecf20Sopenharmony_ci		     VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY,
37138c2ecf20Sopenharmony_ci		     VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG,
37148c2ecf20Sopenharmony_ci			0, &data0, &data1);
37158c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
37168c2ecf20Sopenharmony_ci		goto exit;
37178c2ecf20Sopenharmony_ci
37188c2ecf20Sopenharmony_ci	data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) |
37198c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3));
37208c2ecf20Sopenharmony_ci
37218c2ecf20Sopenharmony_ci	data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_EN |
37228c2ecf20Sopenharmony_ci	VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(bucket_size) |
37238c2ecf20Sopenharmony_ci	VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(algorithm);
37248c2ecf20Sopenharmony_ci
37258c2ecf20Sopenharmony_ci	if (hash_type->hash_type_tcpipv4_en)
37268c2ecf20Sopenharmony_ci		data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV4_EN;
37278c2ecf20Sopenharmony_ci
37288c2ecf20Sopenharmony_ci	if (hash_type->hash_type_ipv4_en)
37298c2ecf20Sopenharmony_ci		data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV4_EN;
37308c2ecf20Sopenharmony_ci
37318c2ecf20Sopenharmony_ci	if (hash_type->hash_type_tcpipv6_en)
37328c2ecf20Sopenharmony_ci		data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV6_EN;
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ci	if (hash_type->hash_type_ipv6_en)
37358c2ecf20Sopenharmony_ci		data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV6_EN;
37368c2ecf20Sopenharmony_ci
37378c2ecf20Sopenharmony_ci	if (hash_type->hash_type_tcpipv6ex_en)
37388c2ecf20Sopenharmony_ci		data0 |=
37398c2ecf20Sopenharmony_ci		VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_TCP_IPV6_EX_EN;
37408c2ecf20Sopenharmony_ci
37418c2ecf20Sopenharmony_ci	if (hash_type->hash_type_ipv6ex_en)
37428c2ecf20Sopenharmony_ci		data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_RTH_IPV6_EX_EN;
37438c2ecf20Sopenharmony_ci
37448c2ecf20Sopenharmony_ci	if (VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_RTH_GEN_ACTIVE_TABLE(data0))
37458c2ecf20Sopenharmony_ci		data0 &= ~VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ACTIVE_TABLE;
37468c2ecf20Sopenharmony_ci	else
37478c2ecf20Sopenharmony_ci		data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ACTIVE_TABLE;
37488c2ecf20Sopenharmony_ci
37498c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_rts_table_set(vp,
37508c2ecf20Sopenharmony_ci		VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY,
37518c2ecf20Sopenharmony_ci		VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG,
37528c2ecf20Sopenharmony_ci		0, data0, 0);
37538c2ecf20Sopenharmony_ciexit:
37548c2ecf20Sopenharmony_ci	return status;
37558c2ecf20Sopenharmony_ci}
37568c2ecf20Sopenharmony_ci
37578c2ecf20Sopenharmony_cistatic void
37588c2ecf20Sopenharmony_civxge_hw_rts_rth_data0_data1_get(u32 j, u64 *data0, u64 *data1,
37598c2ecf20Sopenharmony_ci				u16 flag, u8 *itable)
37608c2ecf20Sopenharmony_ci{
37618c2ecf20Sopenharmony_ci	switch (flag) {
37628c2ecf20Sopenharmony_ci	case 1:
37638c2ecf20Sopenharmony_ci		*data0 = VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_NUM(j)|
37648c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_ENTRY_EN |
37658c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_DATA(
37668c2ecf20Sopenharmony_ci			itable[j]);
37678c2ecf20Sopenharmony_ci		fallthrough;
37688c2ecf20Sopenharmony_ci	case 2:
37698c2ecf20Sopenharmony_ci		*data0 |=
37708c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_NUM(j)|
37718c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_ENTRY_EN |
37728c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_DATA(
37738c2ecf20Sopenharmony_ci			itable[j]);
37748c2ecf20Sopenharmony_ci		fallthrough;
37758c2ecf20Sopenharmony_ci	case 3:
37768c2ecf20Sopenharmony_ci		*data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_NUM(j)|
37778c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_ENTRY_EN |
37788c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_DATA(
37798c2ecf20Sopenharmony_ci			itable[j]);
37808c2ecf20Sopenharmony_ci		fallthrough;
37818c2ecf20Sopenharmony_ci	case 4:
37828c2ecf20Sopenharmony_ci		*data1 |=
37838c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_NUM(j)|
37848c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_ENTRY_EN |
37858c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_DATA(
37868c2ecf20Sopenharmony_ci			itable[j]);
37878c2ecf20Sopenharmony_ci	default:
37888c2ecf20Sopenharmony_ci		return;
37898c2ecf20Sopenharmony_ci	}
37908c2ecf20Sopenharmony_ci}
37918c2ecf20Sopenharmony_ci/*
37928c2ecf20Sopenharmony_ci * vxge_hw_vpath_rts_rth_itable_set - Set/configure indirection table (IT).
37938c2ecf20Sopenharmony_ci */
37948c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_rts_rth_itable_set(
37958c2ecf20Sopenharmony_ci			struct __vxge_hw_vpath_handle **vpath_handles,
37968c2ecf20Sopenharmony_ci			u32 vpath_count,
37978c2ecf20Sopenharmony_ci			u8 *mtable,
37988c2ecf20Sopenharmony_ci			u8 *itable,
37998c2ecf20Sopenharmony_ci			u32 itable_size)
38008c2ecf20Sopenharmony_ci{
38018c2ecf20Sopenharmony_ci	u32 i, j, action, rts_table;
38028c2ecf20Sopenharmony_ci	u64 data0;
38038c2ecf20Sopenharmony_ci	u64 data1;
38048c2ecf20Sopenharmony_ci	u32 max_entries;
38058c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
38068c2ecf20Sopenharmony_ci	struct __vxge_hw_vpath_handle *vp = vpath_handles[0];
38078c2ecf20Sopenharmony_ci
38088c2ecf20Sopenharmony_ci	if (vp == NULL) {
38098c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
38108c2ecf20Sopenharmony_ci		goto exit;
38118c2ecf20Sopenharmony_ci	}
38128c2ecf20Sopenharmony_ci
38138c2ecf20Sopenharmony_ci	max_entries = (((u32)1) << itable_size);
38148c2ecf20Sopenharmony_ci
38158c2ecf20Sopenharmony_ci	if (vp->vpath->hldev->config.rth_it_type
38168c2ecf20Sopenharmony_ci				== VXGE_HW_RTH_IT_TYPE_SOLO_IT) {
38178c2ecf20Sopenharmony_ci		action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY;
38188c2ecf20Sopenharmony_ci		rts_table =
38198c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_SOLO_IT;
38208c2ecf20Sopenharmony_ci
38218c2ecf20Sopenharmony_ci		for (j = 0; j < max_entries; j++) {
38228c2ecf20Sopenharmony_ci
38238c2ecf20Sopenharmony_ci			data1 = 0;
38248c2ecf20Sopenharmony_ci
38258c2ecf20Sopenharmony_ci			data0 =
38268c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_BUCKET_DATA(
38278c2ecf20Sopenharmony_ci				itable[j]);
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci			status = __vxge_hw_vpath_rts_table_set(vpath_handles[0],
38308c2ecf20Sopenharmony_ci				action, rts_table, j, data0, data1);
38318c2ecf20Sopenharmony_ci
38328c2ecf20Sopenharmony_ci			if (status != VXGE_HW_OK)
38338c2ecf20Sopenharmony_ci				goto exit;
38348c2ecf20Sopenharmony_ci		}
38358c2ecf20Sopenharmony_ci
38368c2ecf20Sopenharmony_ci		for (j = 0; j < max_entries; j++) {
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci			data1 = 0;
38398c2ecf20Sopenharmony_ci
38408c2ecf20Sopenharmony_ci			data0 =
38418c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_ENTRY_EN |
38428c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_SOLO_IT_BUCKET_DATA(
38438c2ecf20Sopenharmony_ci				itable[j]);
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci			status = __vxge_hw_vpath_rts_table_set(
38468c2ecf20Sopenharmony_ci				vpath_handles[mtable[itable[j]]], action,
38478c2ecf20Sopenharmony_ci				rts_table, j, data0, data1);
38488c2ecf20Sopenharmony_ci
38498c2ecf20Sopenharmony_ci			if (status != VXGE_HW_OK)
38508c2ecf20Sopenharmony_ci				goto exit;
38518c2ecf20Sopenharmony_ci		}
38528c2ecf20Sopenharmony_ci	} else {
38538c2ecf20Sopenharmony_ci		action = VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_WRITE_ENTRY;
38548c2ecf20Sopenharmony_ci		rts_table =
38558c2ecf20Sopenharmony_ci			VXGE_HW_RTS_ACS_STEER_CTRL_DATA_STRUCT_SEL_RTH_MULTI_IT;
38568c2ecf20Sopenharmony_ci		for (i = 0; i < vpath_count; i++) {
38578c2ecf20Sopenharmony_ci
38588c2ecf20Sopenharmony_ci			for (j = 0; j < max_entries;) {
38598c2ecf20Sopenharmony_ci
38608c2ecf20Sopenharmony_ci				data0 = 0;
38618c2ecf20Sopenharmony_ci				data1 = 0;
38628c2ecf20Sopenharmony_ci
38638c2ecf20Sopenharmony_ci				while (j < max_entries) {
38648c2ecf20Sopenharmony_ci					if (mtable[itable[j]] != i) {
38658c2ecf20Sopenharmony_ci						j++;
38668c2ecf20Sopenharmony_ci						continue;
38678c2ecf20Sopenharmony_ci					}
38688c2ecf20Sopenharmony_ci					vxge_hw_rts_rth_data0_data1_get(j,
38698c2ecf20Sopenharmony_ci						&data0, &data1, 1, itable);
38708c2ecf20Sopenharmony_ci					j++;
38718c2ecf20Sopenharmony_ci					break;
38728c2ecf20Sopenharmony_ci				}
38738c2ecf20Sopenharmony_ci
38748c2ecf20Sopenharmony_ci				while (j < max_entries) {
38758c2ecf20Sopenharmony_ci					if (mtable[itable[j]] != i) {
38768c2ecf20Sopenharmony_ci						j++;
38778c2ecf20Sopenharmony_ci						continue;
38788c2ecf20Sopenharmony_ci					}
38798c2ecf20Sopenharmony_ci					vxge_hw_rts_rth_data0_data1_get(j,
38808c2ecf20Sopenharmony_ci						&data0, &data1, 2, itable);
38818c2ecf20Sopenharmony_ci					j++;
38828c2ecf20Sopenharmony_ci					break;
38838c2ecf20Sopenharmony_ci				}
38848c2ecf20Sopenharmony_ci
38858c2ecf20Sopenharmony_ci				while (j < max_entries) {
38868c2ecf20Sopenharmony_ci					if (mtable[itable[j]] != i) {
38878c2ecf20Sopenharmony_ci						j++;
38888c2ecf20Sopenharmony_ci						continue;
38898c2ecf20Sopenharmony_ci					}
38908c2ecf20Sopenharmony_ci					vxge_hw_rts_rth_data0_data1_get(j,
38918c2ecf20Sopenharmony_ci						&data0, &data1, 3, itable);
38928c2ecf20Sopenharmony_ci					j++;
38938c2ecf20Sopenharmony_ci					break;
38948c2ecf20Sopenharmony_ci				}
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci				while (j < max_entries) {
38978c2ecf20Sopenharmony_ci					if (mtable[itable[j]] != i) {
38988c2ecf20Sopenharmony_ci						j++;
38998c2ecf20Sopenharmony_ci						continue;
39008c2ecf20Sopenharmony_ci					}
39018c2ecf20Sopenharmony_ci					vxge_hw_rts_rth_data0_data1_get(j,
39028c2ecf20Sopenharmony_ci						&data0, &data1, 4, itable);
39038c2ecf20Sopenharmony_ci					j++;
39048c2ecf20Sopenharmony_ci					break;
39058c2ecf20Sopenharmony_ci				}
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_ci				if (data0 != 0) {
39088c2ecf20Sopenharmony_ci					status = __vxge_hw_vpath_rts_table_set(
39098c2ecf20Sopenharmony_ci							vpath_handles[i],
39108c2ecf20Sopenharmony_ci							action, rts_table,
39118c2ecf20Sopenharmony_ci							0, data0, data1);
39128c2ecf20Sopenharmony_ci
39138c2ecf20Sopenharmony_ci					if (status != VXGE_HW_OK)
39148c2ecf20Sopenharmony_ci						goto exit;
39158c2ecf20Sopenharmony_ci				}
39168c2ecf20Sopenharmony_ci			}
39178c2ecf20Sopenharmony_ci		}
39188c2ecf20Sopenharmony_ci	}
39198c2ecf20Sopenharmony_ciexit:
39208c2ecf20Sopenharmony_ci	return status;
39218c2ecf20Sopenharmony_ci}
39228c2ecf20Sopenharmony_ci
39238c2ecf20Sopenharmony_ci/**
39248c2ecf20Sopenharmony_ci * vxge_hw_vpath_check_leak - Check for memory leak
39258c2ecf20Sopenharmony_ci * @ring: Handle to the ring object used for receive
39268c2ecf20Sopenharmony_ci *
39278c2ecf20Sopenharmony_ci * If PRC_RXD_DOORBELL_VPn.NEW_QW_CNT is larger or equal to
39288c2ecf20Sopenharmony_ci * PRC_CFG6_VPn.RXD_SPAT then a leak has occurred.
39298c2ecf20Sopenharmony_ci * Returns: VXGE_HW_FAIL, if leak has occurred.
39308c2ecf20Sopenharmony_ci *
39318c2ecf20Sopenharmony_ci */
39328c2ecf20Sopenharmony_cienum vxge_hw_status
39338c2ecf20Sopenharmony_civxge_hw_vpath_check_leak(struct __vxge_hw_ring *ring)
39348c2ecf20Sopenharmony_ci{
39358c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
39368c2ecf20Sopenharmony_ci	u64 rxd_new_count, rxd_spat;
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci	if (ring == NULL)
39398c2ecf20Sopenharmony_ci		return status;
39408c2ecf20Sopenharmony_ci
39418c2ecf20Sopenharmony_ci	rxd_new_count = readl(&ring->vp_reg->prc_rxd_doorbell);
39428c2ecf20Sopenharmony_ci	rxd_spat = readq(&ring->vp_reg->prc_cfg6);
39438c2ecf20Sopenharmony_ci	rxd_spat = VXGE_HW_PRC_CFG6_RXD_SPAT(rxd_spat);
39448c2ecf20Sopenharmony_ci
39458c2ecf20Sopenharmony_ci	if (rxd_new_count >= rxd_spat)
39468c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
39478c2ecf20Sopenharmony_ci
39488c2ecf20Sopenharmony_ci	return status;
39498c2ecf20Sopenharmony_ci}
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci/*
39528c2ecf20Sopenharmony_ci * __vxge_hw_vpath_mgmt_read
39538c2ecf20Sopenharmony_ci * This routine reads the vpath_mgmt registers
39548c2ecf20Sopenharmony_ci */
39558c2ecf20Sopenharmony_cistatic enum vxge_hw_status
39568c2ecf20Sopenharmony_ci__vxge_hw_vpath_mgmt_read(
39578c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev,
39588c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath)
39598c2ecf20Sopenharmony_ci{
39608c2ecf20Sopenharmony_ci	u32 i, mtu = 0, max_pyld = 0;
39618c2ecf20Sopenharmony_ci	u64 val64;
39628c2ecf20Sopenharmony_ci
39638c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAC_MAX_MAC_PORT_ID; i++) {
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_ci		val64 = readq(&vpath->vpmgmt_reg->
39668c2ecf20Sopenharmony_ci				rxmac_cfg0_port_vpmgmt_clone[i]);
39678c2ecf20Sopenharmony_ci		max_pyld =
39688c2ecf20Sopenharmony_ci			(u32)
39698c2ecf20Sopenharmony_ci			VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_GET_MAX_PYLD_LEN
39708c2ecf20Sopenharmony_ci			(val64);
39718c2ecf20Sopenharmony_ci		if (mtu < max_pyld)
39728c2ecf20Sopenharmony_ci			mtu = max_pyld;
39738c2ecf20Sopenharmony_ci	}
39748c2ecf20Sopenharmony_ci
39758c2ecf20Sopenharmony_ci	vpath->max_mtu = mtu + VXGE_HW_MAC_HEADER_MAX_SIZE;
39768c2ecf20Sopenharmony_ci
39778c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vpmgmt_reg->xmac_vsport_choices_vp);
39788c2ecf20Sopenharmony_ci
39798c2ecf20Sopenharmony_ci	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
39808c2ecf20Sopenharmony_ci		if (val64 & vxge_mBIT(i))
39818c2ecf20Sopenharmony_ci			vpath->vsport_number = i;
39828c2ecf20Sopenharmony_ci	}
39838c2ecf20Sopenharmony_ci
39848c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vpmgmt_reg->xgmac_gen_status_vpmgmt_clone);
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_ci	if (val64 & VXGE_HW_XGMAC_GEN_STATUS_VPMGMT_CLONE_XMACJ_NTWK_OK)
39878c2ecf20Sopenharmony_ci		VXGE_HW_DEVICE_LINK_STATE_SET(vpath->hldev, VXGE_HW_LINK_UP);
39888c2ecf20Sopenharmony_ci	else
39898c2ecf20Sopenharmony_ci		VXGE_HW_DEVICE_LINK_STATE_SET(vpath->hldev, VXGE_HW_LINK_DOWN);
39908c2ecf20Sopenharmony_ci
39918c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
39928c2ecf20Sopenharmony_ci}
39938c2ecf20Sopenharmony_ci
39948c2ecf20Sopenharmony_ci/*
39958c2ecf20Sopenharmony_ci * __vxge_hw_vpath_reset_check - Check if resetting the vpath completed
39968c2ecf20Sopenharmony_ci * This routine checks the vpath_rst_in_prog register to see if
39978c2ecf20Sopenharmony_ci * adapter completed the reset process for the vpath
39988c2ecf20Sopenharmony_ci */
39998c2ecf20Sopenharmony_cistatic enum vxge_hw_status
40008c2ecf20Sopenharmony_ci__vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath)
40018c2ecf20Sopenharmony_ci{
40028c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
40038c2ecf20Sopenharmony_ci
40048c2ecf20Sopenharmony_ci	status = __vxge_hw_device_register_poll(
40058c2ecf20Sopenharmony_ci			&vpath->hldev->common_reg->vpath_rst_in_prog,
40068c2ecf20Sopenharmony_ci			VXGE_HW_VPATH_RST_IN_PROG_VPATH_RST_IN_PROG(
40078c2ecf20Sopenharmony_ci				1 << (16 - vpath->vp_id)),
40088c2ecf20Sopenharmony_ci			vpath->hldev->config.device_poll_millis);
40098c2ecf20Sopenharmony_ci
40108c2ecf20Sopenharmony_ci	return status;
40118c2ecf20Sopenharmony_ci}
40128c2ecf20Sopenharmony_ci
40138c2ecf20Sopenharmony_ci/*
40148c2ecf20Sopenharmony_ci * __vxge_hw_vpath_reset
40158c2ecf20Sopenharmony_ci * This routine resets the vpath on the device
40168c2ecf20Sopenharmony_ci */
40178c2ecf20Sopenharmony_cistatic enum vxge_hw_status
40188c2ecf20Sopenharmony_ci__vxge_hw_vpath_reset(struct __vxge_hw_device *hldev, u32 vp_id)
40198c2ecf20Sopenharmony_ci{
40208c2ecf20Sopenharmony_ci	u64 val64;
40218c2ecf20Sopenharmony_ci
40228c2ecf20Sopenharmony_ci	val64 = VXGE_HW_CMN_RSTHDLR_CFG0_SW_RESET_VPATH(1 << (16 - vp_id));
40238c2ecf20Sopenharmony_ci
40248c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
40258c2ecf20Sopenharmony_ci				&hldev->common_reg->cmn_rsthdlr_cfg0);
40268c2ecf20Sopenharmony_ci
40278c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
40288c2ecf20Sopenharmony_ci}
40298c2ecf20Sopenharmony_ci
40308c2ecf20Sopenharmony_ci/*
40318c2ecf20Sopenharmony_ci * __vxge_hw_vpath_sw_reset
40328c2ecf20Sopenharmony_ci * This routine resets the vpath structures
40338c2ecf20Sopenharmony_ci */
40348c2ecf20Sopenharmony_cistatic enum vxge_hw_status
40358c2ecf20Sopenharmony_ci__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *hldev, u32 vp_id)
40368c2ecf20Sopenharmony_ci{
40378c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
40388c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
40398c2ecf20Sopenharmony_ci
40408c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
40418c2ecf20Sopenharmony_ci
40428c2ecf20Sopenharmony_ci	if (vpath->ringh) {
40438c2ecf20Sopenharmony_ci		status = __vxge_hw_ring_reset(vpath->ringh);
40448c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
40458c2ecf20Sopenharmony_ci			goto exit;
40468c2ecf20Sopenharmony_ci	}
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ci	if (vpath->fifoh)
40498c2ecf20Sopenharmony_ci		status = __vxge_hw_fifo_reset(vpath->fifoh);
40508c2ecf20Sopenharmony_ciexit:
40518c2ecf20Sopenharmony_ci	return status;
40528c2ecf20Sopenharmony_ci}
40538c2ecf20Sopenharmony_ci
40548c2ecf20Sopenharmony_ci/*
40558c2ecf20Sopenharmony_ci * __vxge_hw_vpath_prc_configure
40568c2ecf20Sopenharmony_ci * This routine configures the prc registers of virtual path using the config
40578c2ecf20Sopenharmony_ci * passed
40588c2ecf20Sopenharmony_ci */
40598c2ecf20Sopenharmony_cistatic void
40608c2ecf20Sopenharmony_ci__vxge_hw_vpath_prc_configure(struct __vxge_hw_device *hldev, u32 vp_id)
40618c2ecf20Sopenharmony_ci{
40628c2ecf20Sopenharmony_ci	u64 val64;
40638c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
40648c2ecf20Sopenharmony_ci	struct vxge_hw_vp_config *vp_config;
40658c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
40668c2ecf20Sopenharmony_ci
40678c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
40688c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
40698c2ecf20Sopenharmony_ci	vp_config = vpath->vp_config;
40708c2ecf20Sopenharmony_ci
40718c2ecf20Sopenharmony_ci	if (vp_config->ring.enable == VXGE_HW_RING_DISABLE)
40728c2ecf20Sopenharmony_ci		return;
40738c2ecf20Sopenharmony_ci
40748c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->prc_cfg1);
40758c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_PRC_CFG1_RTI_TINT_DISABLE;
40768c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->prc_cfg1);
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->prc_cfg6);
40798c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_PRC_CFG6_DOORBELL_MODE_EN;
40808c2ecf20Sopenharmony_ci	writeq(val64, &vpath->vp_reg->prc_cfg6);
40818c2ecf20Sopenharmony_ci
40828c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->prc_cfg7);
40838c2ecf20Sopenharmony_ci
40848c2ecf20Sopenharmony_ci	if (vpath->vp_config->ring.scatter_mode !=
40858c2ecf20Sopenharmony_ci		VXGE_HW_RING_SCATTER_MODE_USE_FLASH_DEFAULT) {
40868c2ecf20Sopenharmony_ci
40878c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_PRC_CFG7_SCATTER_MODE(0x3);
40888c2ecf20Sopenharmony_ci
40898c2ecf20Sopenharmony_ci		switch (vpath->vp_config->ring.scatter_mode) {
40908c2ecf20Sopenharmony_ci		case VXGE_HW_RING_SCATTER_MODE_A:
40918c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_PRC_CFG7_SCATTER_MODE(
40928c2ecf20Sopenharmony_ci					VXGE_HW_PRC_CFG7_SCATTER_MODE_A);
40938c2ecf20Sopenharmony_ci			break;
40948c2ecf20Sopenharmony_ci		case VXGE_HW_RING_SCATTER_MODE_B:
40958c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_PRC_CFG7_SCATTER_MODE(
40968c2ecf20Sopenharmony_ci					VXGE_HW_PRC_CFG7_SCATTER_MODE_B);
40978c2ecf20Sopenharmony_ci			break;
40988c2ecf20Sopenharmony_ci		case VXGE_HW_RING_SCATTER_MODE_C:
40998c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_PRC_CFG7_SCATTER_MODE(
41008c2ecf20Sopenharmony_ci					VXGE_HW_PRC_CFG7_SCATTER_MODE_C);
41018c2ecf20Sopenharmony_ci			break;
41028c2ecf20Sopenharmony_ci		}
41038c2ecf20Sopenharmony_ci	}
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->prc_cfg7);
41068c2ecf20Sopenharmony_ci
41078c2ecf20Sopenharmony_ci	writeq(VXGE_HW_PRC_CFG5_RXD0_ADD(
41088c2ecf20Sopenharmony_ci				__vxge_hw_ring_first_block_address_get(
41098c2ecf20Sopenharmony_ci					vpath->ringh) >> 3), &vp_reg->prc_cfg5);
41108c2ecf20Sopenharmony_ci
41118c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->prc_cfg4);
41128c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_PRC_CFG4_IN_SVC;
41138c2ecf20Sopenharmony_ci	val64 &= ~VXGE_HW_PRC_CFG4_RING_MODE(0x3);
41148c2ecf20Sopenharmony_ci
41158c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_PRC_CFG4_RING_MODE(
41168c2ecf20Sopenharmony_ci			VXGE_HW_PRC_CFG4_RING_MODE_ONE_BUFFER);
41178c2ecf20Sopenharmony_ci
41188c2ecf20Sopenharmony_ci	if (hldev->config.rth_en == VXGE_HW_RTH_DISABLE)
41198c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_PRC_CFG4_RTH_DISABLE;
41208c2ecf20Sopenharmony_ci	else
41218c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_PRC_CFG4_RTH_DISABLE;
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->prc_cfg4);
41248c2ecf20Sopenharmony_ci}
41258c2ecf20Sopenharmony_ci
41268c2ecf20Sopenharmony_ci/*
41278c2ecf20Sopenharmony_ci * __vxge_hw_vpath_kdfc_configure
41288c2ecf20Sopenharmony_ci * This routine configures the kdfc registers of virtual path using the
41298c2ecf20Sopenharmony_ci * config passed
41308c2ecf20Sopenharmony_ci */
41318c2ecf20Sopenharmony_cistatic enum vxge_hw_status
41328c2ecf20Sopenharmony_ci__vxge_hw_vpath_kdfc_configure(struct __vxge_hw_device *hldev, u32 vp_id)
41338c2ecf20Sopenharmony_ci{
41348c2ecf20Sopenharmony_ci	u64 val64;
41358c2ecf20Sopenharmony_ci	u64 vpath_stride;
41368c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
41378c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
41388c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
41398c2ecf20Sopenharmony_ci
41408c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
41418c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
41428c2ecf20Sopenharmony_ci	status = __vxge_hw_kdfc_swapper_set(hldev->legacy_reg, vp_reg);
41438c2ecf20Sopenharmony_ci
41448c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
41458c2ecf20Sopenharmony_ci		goto exit;
41468c2ecf20Sopenharmony_ci
41478c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->kdfc_drbl_triplet_total);
41488c2ecf20Sopenharmony_ci
41498c2ecf20Sopenharmony_ci	vpath->max_kdfc_db =
41508c2ecf20Sopenharmony_ci		(u32)VXGE_HW_KDFC_DRBL_TRIPLET_TOTAL_GET_KDFC_MAX_SIZE(
41518c2ecf20Sopenharmony_ci			val64+1)/2;
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_ci	if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci		vpath->max_nofl_db = vpath->max_kdfc_db;
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci		if (vpath->max_nofl_db <
41588c2ecf20Sopenharmony_ci			((vpath->vp_config->fifo.memblock_size /
41598c2ecf20Sopenharmony_ci			(vpath->vp_config->fifo.max_frags *
41608c2ecf20Sopenharmony_ci			sizeof(struct vxge_hw_fifo_txd))) *
41618c2ecf20Sopenharmony_ci			vpath->vp_config->fifo.fifo_blocks)) {
41628c2ecf20Sopenharmony_ci
41638c2ecf20Sopenharmony_ci			return VXGE_HW_BADCFG_FIFO_BLOCKS;
41648c2ecf20Sopenharmony_ci		}
41658c2ecf20Sopenharmony_ci		val64 = VXGE_HW_KDFC_FIFO_TRPL_PARTITION_LENGTH_0(
41668c2ecf20Sopenharmony_ci				(vpath->max_nofl_db*2)-1);
41678c2ecf20Sopenharmony_ci	}
41688c2ecf20Sopenharmony_ci
41698c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->kdfc_fifo_trpl_partition);
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci	writeq(VXGE_HW_KDFC_FIFO_TRPL_CTRL_TRIPLET_ENABLE,
41728c2ecf20Sopenharmony_ci		&vp_reg->kdfc_fifo_trpl_ctrl);
41738c2ecf20Sopenharmony_ci
41748c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->kdfc_trpl_fifo_0_ctrl);
41758c2ecf20Sopenharmony_ci
41768c2ecf20Sopenharmony_ci	val64 &= ~(VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(0x3) |
41778c2ecf20Sopenharmony_ci		   VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(0xFF));
41788c2ecf20Sopenharmony_ci
41798c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE(
41808c2ecf20Sopenharmony_ci		 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_MODE_NON_OFFLOAD_ONLY) |
41818c2ecf20Sopenharmony_ci#ifndef __BIG_ENDIAN
41828c2ecf20Sopenharmony_ci		 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SWAP_EN |
41838c2ecf20Sopenharmony_ci#endif
41848c2ecf20Sopenharmony_ci		 VXGE_HW_KDFC_TRPL_FIFO_0_CTRL_SELECT(0);
41858c2ecf20Sopenharmony_ci
41868c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->kdfc_trpl_fifo_0_ctrl);
41878c2ecf20Sopenharmony_ci	writeq((u64)0, &vp_reg->kdfc_trpl_fifo_0_wb_address);
41888c2ecf20Sopenharmony_ci	wmb();
41898c2ecf20Sopenharmony_ci	vpath_stride = readq(&hldev->toc_reg->toc_kdfc_vpath_stride);
41908c2ecf20Sopenharmony_ci
41918c2ecf20Sopenharmony_ci	vpath->nofl_db =
41928c2ecf20Sopenharmony_ci		(struct __vxge_hw_non_offload_db_wrapper __iomem *)
41938c2ecf20Sopenharmony_ci		(hldev->kdfc + (vp_id *
41948c2ecf20Sopenharmony_ci		VXGE_HW_TOC_KDFC_VPATH_STRIDE_GET_TOC_KDFC_VPATH_STRIDE(
41958c2ecf20Sopenharmony_ci					vpath_stride)));
41968c2ecf20Sopenharmony_ciexit:
41978c2ecf20Sopenharmony_ci	return status;
41988c2ecf20Sopenharmony_ci}
41998c2ecf20Sopenharmony_ci
42008c2ecf20Sopenharmony_ci/*
42018c2ecf20Sopenharmony_ci * __vxge_hw_vpath_mac_configure
42028c2ecf20Sopenharmony_ci * This routine configures the mac of virtual path using the config passed
42038c2ecf20Sopenharmony_ci */
42048c2ecf20Sopenharmony_cistatic enum vxge_hw_status
42058c2ecf20Sopenharmony_ci__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *hldev, u32 vp_id)
42068c2ecf20Sopenharmony_ci{
42078c2ecf20Sopenharmony_ci	u64 val64;
42088c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
42098c2ecf20Sopenharmony_ci	struct vxge_hw_vp_config *vp_config;
42108c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
42118c2ecf20Sopenharmony_ci
42128c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
42138c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
42148c2ecf20Sopenharmony_ci	vp_config = vpath->vp_config;
42158c2ecf20Sopenharmony_ci
42168c2ecf20Sopenharmony_ci	writeq(VXGE_HW_XMAC_VSPORT_CHOICE_VSPORT_NUMBER(
42178c2ecf20Sopenharmony_ci			vpath->vsport_number), &vp_reg->xmac_vsport_choice);
42188c2ecf20Sopenharmony_ci
42198c2ecf20Sopenharmony_ci	if (vp_config->ring.enable == VXGE_HW_RING_ENABLE) {
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->xmac_rpa_vcfg);
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ci		if (vp_config->rpa_strip_vlan_tag !=
42248c2ecf20Sopenharmony_ci			VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_USE_FLASH_DEFAULT) {
42258c2ecf20Sopenharmony_ci			if (vp_config->rpa_strip_vlan_tag)
42268c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_XMAC_RPA_VCFG_STRIP_VLAN_TAG;
42278c2ecf20Sopenharmony_ci			else
42288c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_XMAC_RPA_VCFG_STRIP_VLAN_TAG;
42298c2ecf20Sopenharmony_ci		}
42308c2ecf20Sopenharmony_ci
42318c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->xmac_rpa_vcfg);
42328c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->rxmac_vcfg0);
42338c2ecf20Sopenharmony_ci
42348c2ecf20Sopenharmony_ci		if (vp_config->mtu !=
42358c2ecf20Sopenharmony_ci				VXGE_HW_VPATH_USE_FLASH_DEFAULT_INITIAL_MTU) {
42368c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
42378c2ecf20Sopenharmony_ci			if ((vp_config->mtu  +
42388c2ecf20Sopenharmony_ci				VXGE_HW_MAC_HEADER_MAX_SIZE) < vpath->max_mtu)
42398c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(
42408c2ecf20Sopenharmony_ci					vp_config->mtu  +
42418c2ecf20Sopenharmony_ci					VXGE_HW_MAC_HEADER_MAX_SIZE);
42428c2ecf20Sopenharmony_ci			else
42438c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(
42448c2ecf20Sopenharmony_ci					vpath->max_mtu);
42458c2ecf20Sopenharmony_ci		}
42468c2ecf20Sopenharmony_ci
42478c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->rxmac_vcfg0);
42488c2ecf20Sopenharmony_ci
42498c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->rxmac_vcfg1);
42508c2ecf20Sopenharmony_ci
42518c2ecf20Sopenharmony_ci		val64 &= ~(VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_BD_MODE(0x3) |
42528c2ecf20Sopenharmony_ci			VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_EN_MODE);
42538c2ecf20Sopenharmony_ci
42548c2ecf20Sopenharmony_ci		if (hldev->config.rth_it_type ==
42558c2ecf20Sopenharmony_ci				VXGE_HW_RTH_IT_TYPE_MULTI_IT) {
42568c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_BD_MODE(
42578c2ecf20Sopenharmony_ci				0x2) |
42588c2ecf20Sopenharmony_ci				VXGE_HW_RXMAC_VCFG1_RTS_RTH_MULTI_IT_EN_MODE;
42598c2ecf20Sopenharmony_ci		}
42608c2ecf20Sopenharmony_ci
42618c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->rxmac_vcfg1);
42628c2ecf20Sopenharmony_ci	}
42638c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
42648c2ecf20Sopenharmony_ci}
42658c2ecf20Sopenharmony_ci
42668c2ecf20Sopenharmony_ci/*
42678c2ecf20Sopenharmony_ci * __vxge_hw_vpath_tim_configure
42688c2ecf20Sopenharmony_ci * This routine configures the tim registers of virtual path using the config
42698c2ecf20Sopenharmony_ci * passed
42708c2ecf20Sopenharmony_ci */
42718c2ecf20Sopenharmony_cistatic enum vxge_hw_status
42728c2ecf20Sopenharmony_ci__vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
42738c2ecf20Sopenharmony_ci{
42748c2ecf20Sopenharmony_ci	u64 val64;
42758c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
42768c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
42778c2ecf20Sopenharmony_ci	struct vxge_hw_vp_config *config;
42788c2ecf20Sopenharmony_ci
42798c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
42808c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
42818c2ecf20Sopenharmony_ci	config = vpath->vp_config;
42828c2ecf20Sopenharmony_ci
42838c2ecf20Sopenharmony_ci	writeq(0, &vp_reg->tim_dest_addr);
42848c2ecf20Sopenharmony_ci	writeq(0, &vp_reg->tim_vpath_map);
42858c2ecf20Sopenharmony_ci	writeq(0, &vp_reg->tim_bitmap);
42868c2ecf20Sopenharmony_ci	writeq(0, &vp_reg->tim_remap);
42878c2ecf20Sopenharmony_ci
42888c2ecf20Sopenharmony_ci	if (config->ring.enable == VXGE_HW_RING_ENABLE)
42898c2ecf20Sopenharmony_ci		writeq(VXGE_HW_TIM_RING_ASSN_INT_NUM(
42908c2ecf20Sopenharmony_ci			(vp_id * VXGE_HW_MAX_INTR_PER_VP) +
42918c2ecf20Sopenharmony_ci			VXGE_HW_VPATH_INTR_RX), &vp_reg->tim_ring_assn);
42928c2ecf20Sopenharmony_ci
42938c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->tim_pci_cfg);
42948c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_TIM_PCI_CFG_ADD_PAD;
42958c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_pci_cfg);
42968c2ecf20Sopenharmony_ci
42978c2ecf20Sopenharmony_ci	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
42988c2ecf20Sopenharmony_ci
42998c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ci		if (config->tti.btimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
43028c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
43038c2ecf20Sopenharmony_ci				0x3ffffff);
43048c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
43058c2ecf20Sopenharmony_ci					config->tti.btimer_val);
43068c2ecf20Sopenharmony_ci		}
43078c2ecf20Sopenharmony_ci
43088c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BITMP_EN;
43098c2ecf20Sopenharmony_ci
43108c2ecf20Sopenharmony_ci		if (config->tti.timer_ac_en != VXGE_HW_USE_FLASH_DEFAULT) {
43118c2ecf20Sopenharmony_ci			if (config->tti.timer_ac_en)
43128c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
43138c2ecf20Sopenharmony_ci			else
43148c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
43158c2ecf20Sopenharmony_ci		}
43168c2ecf20Sopenharmony_ci
43178c2ecf20Sopenharmony_ci		if (config->tti.timer_ci_en != VXGE_HW_USE_FLASH_DEFAULT) {
43188c2ecf20Sopenharmony_ci			if (config->tti.timer_ci_en)
43198c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
43208c2ecf20Sopenharmony_ci			else
43218c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
43228c2ecf20Sopenharmony_ci		}
43238c2ecf20Sopenharmony_ci
43248c2ecf20Sopenharmony_ci		if (config->tti.urange_a != VXGE_HW_USE_FLASH_DEFAULT) {
43258c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(0x3f);
43268c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(
43278c2ecf20Sopenharmony_ci					config->tti.urange_a);
43288c2ecf20Sopenharmony_ci		}
43298c2ecf20Sopenharmony_ci
43308c2ecf20Sopenharmony_ci		if (config->tti.urange_b != VXGE_HW_USE_FLASH_DEFAULT) {
43318c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(0x3f);
43328c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(
43338c2ecf20Sopenharmony_ci					config->tti.urange_b);
43348c2ecf20Sopenharmony_ci		}
43358c2ecf20Sopenharmony_ci
43368c2ecf20Sopenharmony_ci		if (config->tti.urange_c != VXGE_HW_USE_FLASH_DEFAULT) {
43378c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(0x3f);
43388c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(
43398c2ecf20Sopenharmony_ci					config->tti.urange_c);
43408c2ecf20Sopenharmony_ci		}
43418c2ecf20Sopenharmony_ci
43428c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
43438c2ecf20Sopenharmony_ci		vpath->tim_tti_cfg1_saved = val64;
43448c2ecf20Sopenharmony_ci
43458c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
43468c2ecf20Sopenharmony_ci
43478c2ecf20Sopenharmony_ci		if (config->tti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
43488c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(0xffff);
43498c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(
43508c2ecf20Sopenharmony_ci						config->tti.uec_a);
43518c2ecf20Sopenharmony_ci		}
43528c2ecf20Sopenharmony_ci
43538c2ecf20Sopenharmony_ci		if (config->tti.uec_b != VXGE_HW_USE_FLASH_DEFAULT) {
43548c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(0xffff);
43558c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(
43568c2ecf20Sopenharmony_ci						config->tti.uec_b);
43578c2ecf20Sopenharmony_ci		}
43588c2ecf20Sopenharmony_ci
43598c2ecf20Sopenharmony_ci		if (config->tti.uec_c != VXGE_HW_USE_FLASH_DEFAULT) {
43608c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(0xffff);
43618c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(
43628c2ecf20Sopenharmony_ci						config->tti.uec_c);
43638c2ecf20Sopenharmony_ci		}
43648c2ecf20Sopenharmony_ci
43658c2ecf20Sopenharmony_ci		if (config->tti.uec_d != VXGE_HW_USE_FLASH_DEFAULT) {
43668c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(0xffff);
43678c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(
43688c2ecf20Sopenharmony_ci						config->tti.uec_d);
43698c2ecf20Sopenharmony_ci		}
43708c2ecf20Sopenharmony_ci
43718c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
43728c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
43738c2ecf20Sopenharmony_ci
43748c2ecf20Sopenharmony_ci		if (config->tti.timer_ri_en != VXGE_HW_USE_FLASH_DEFAULT) {
43758c2ecf20Sopenharmony_ci			if (config->tti.timer_ri_en)
43768c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
43778c2ecf20Sopenharmony_ci			else
43788c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
43798c2ecf20Sopenharmony_ci		}
43808c2ecf20Sopenharmony_ci
43818c2ecf20Sopenharmony_ci		if (config->tti.rtimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
43828c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
43838c2ecf20Sopenharmony_ci					0x3ffffff);
43848c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
43858c2ecf20Sopenharmony_ci					config->tti.rtimer_val);
43868c2ecf20Sopenharmony_ci		}
43878c2ecf20Sopenharmony_ci
43888c2ecf20Sopenharmony_ci		if (config->tti.util_sel != VXGE_HW_USE_FLASH_DEFAULT) {
43898c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(0x3f);
43908c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(vp_id);
43918c2ecf20Sopenharmony_ci		}
43928c2ecf20Sopenharmony_ci
43938c2ecf20Sopenharmony_ci		if (config->tti.ltimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
43948c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
43958c2ecf20Sopenharmony_ci					0x3ffffff);
43968c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
43978c2ecf20Sopenharmony_ci					config->tti.ltimer_val);
43988c2ecf20Sopenharmony_ci		}
43998c2ecf20Sopenharmony_ci
44008c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
44018c2ecf20Sopenharmony_ci		vpath->tim_tti_cfg3_saved = val64;
44028c2ecf20Sopenharmony_ci	}
44038c2ecf20Sopenharmony_ci
44048c2ecf20Sopenharmony_ci	if (config->ring.enable == VXGE_HW_RING_ENABLE) {
44058c2ecf20Sopenharmony_ci
44068c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_ci		if (config->rti.btimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
44098c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
44108c2ecf20Sopenharmony_ci					0x3ffffff);
44118c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_BTIMER_VAL(
44128c2ecf20Sopenharmony_ci					config->rti.btimer_val);
44138c2ecf20Sopenharmony_ci		}
44148c2ecf20Sopenharmony_ci
44158c2ecf20Sopenharmony_ci		val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_BITMP_EN;
44168c2ecf20Sopenharmony_ci
44178c2ecf20Sopenharmony_ci		if (config->rti.timer_ac_en != VXGE_HW_USE_FLASH_DEFAULT) {
44188c2ecf20Sopenharmony_ci			if (config->rti.timer_ac_en)
44198c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
44208c2ecf20Sopenharmony_ci			else
44218c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_AC;
44228c2ecf20Sopenharmony_ci		}
44238c2ecf20Sopenharmony_ci
44248c2ecf20Sopenharmony_ci		if (config->rti.timer_ci_en != VXGE_HW_USE_FLASH_DEFAULT) {
44258c2ecf20Sopenharmony_ci			if (config->rti.timer_ci_en)
44268c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
44278c2ecf20Sopenharmony_ci			else
44288c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
44298c2ecf20Sopenharmony_ci		}
44308c2ecf20Sopenharmony_ci
44318c2ecf20Sopenharmony_ci		if (config->rti.urange_a != VXGE_HW_USE_FLASH_DEFAULT) {
44328c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(0x3f);
44338c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_A(
44348c2ecf20Sopenharmony_ci					config->rti.urange_a);
44358c2ecf20Sopenharmony_ci		}
44368c2ecf20Sopenharmony_ci
44378c2ecf20Sopenharmony_ci		if (config->rti.urange_b != VXGE_HW_USE_FLASH_DEFAULT) {
44388c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(0x3f);
44398c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_B(
44408c2ecf20Sopenharmony_ci					config->rti.urange_b);
44418c2ecf20Sopenharmony_ci		}
44428c2ecf20Sopenharmony_ci
44438c2ecf20Sopenharmony_ci		if (config->rti.urange_c != VXGE_HW_USE_FLASH_DEFAULT) {
44448c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(0x3f);
44458c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_URNG_C(
44468c2ecf20Sopenharmony_ci					config->rti.urange_c);
44478c2ecf20Sopenharmony_ci		}
44488c2ecf20Sopenharmony_ci
44498c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
44508c2ecf20Sopenharmony_ci		vpath->tim_rti_cfg1_saved = val64;
44518c2ecf20Sopenharmony_ci
44528c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
44538c2ecf20Sopenharmony_ci
44548c2ecf20Sopenharmony_ci		if (config->rti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
44558c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(0xffff);
44568c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_A(
44578c2ecf20Sopenharmony_ci						config->rti.uec_a);
44588c2ecf20Sopenharmony_ci		}
44598c2ecf20Sopenharmony_ci
44608c2ecf20Sopenharmony_ci		if (config->rti.uec_b != VXGE_HW_USE_FLASH_DEFAULT) {
44618c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(0xffff);
44628c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_B(
44638c2ecf20Sopenharmony_ci						config->rti.uec_b);
44648c2ecf20Sopenharmony_ci		}
44658c2ecf20Sopenharmony_ci
44668c2ecf20Sopenharmony_ci		if (config->rti.uec_c != VXGE_HW_USE_FLASH_DEFAULT) {
44678c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(0xffff);
44688c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_C(
44698c2ecf20Sopenharmony_ci						config->rti.uec_c);
44708c2ecf20Sopenharmony_ci		}
44718c2ecf20Sopenharmony_ci
44728c2ecf20Sopenharmony_ci		if (config->rti.uec_d != VXGE_HW_USE_FLASH_DEFAULT) {
44738c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(0xffff);
44748c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG2_INT_NUM_UEC_D(
44758c2ecf20Sopenharmony_ci						config->rti.uec_d);
44768c2ecf20Sopenharmony_ci		}
44778c2ecf20Sopenharmony_ci
44788c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
44798c2ecf20Sopenharmony_ci		val64 = readq(&vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
44808c2ecf20Sopenharmony_ci
44818c2ecf20Sopenharmony_ci		if (config->rti.timer_ri_en != VXGE_HW_USE_FLASH_DEFAULT) {
44828c2ecf20Sopenharmony_ci			if (config->rti.timer_ri_en)
44838c2ecf20Sopenharmony_ci				val64 |= VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
44848c2ecf20Sopenharmony_ci			else
44858c2ecf20Sopenharmony_ci				val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_TIMER_RI;
44868c2ecf20Sopenharmony_ci		}
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_ci		if (config->rti.rtimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
44898c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
44908c2ecf20Sopenharmony_ci					0x3ffffff);
44918c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(
44928c2ecf20Sopenharmony_ci					config->rti.rtimer_val);
44938c2ecf20Sopenharmony_ci		}
44948c2ecf20Sopenharmony_ci
44958c2ecf20Sopenharmony_ci		if (config->rti.util_sel != VXGE_HW_USE_FLASH_DEFAULT) {
44968c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(0x3f);
44978c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_UTIL_SEL(vp_id);
44988c2ecf20Sopenharmony_ci		}
44998c2ecf20Sopenharmony_ci
45008c2ecf20Sopenharmony_ci		if (config->rti.ltimer_val != VXGE_HW_USE_FLASH_DEFAULT) {
45018c2ecf20Sopenharmony_ci			val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
45028c2ecf20Sopenharmony_ci					0x3ffffff);
45038c2ecf20Sopenharmony_ci			val64 |= VXGE_HW_TIM_CFG3_INT_NUM_LTIMER_VAL(
45048c2ecf20Sopenharmony_ci					config->rti.ltimer_val);
45058c2ecf20Sopenharmony_ci		}
45068c2ecf20Sopenharmony_ci
45078c2ecf20Sopenharmony_ci		writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
45088c2ecf20Sopenharmony_ci		vpath->tim_rti_cfg3_saved = val64;
45098c2ecf20Sopenharmony_ci	}
45108c2ecf20Sopenharmony_ci
45118c2ecf20Sopenharmony_ci	val64 = 0;
45128c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_EINTA]);
45138c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_EINTA]);
45148c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_EINTA]);
45158c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_BMAP]);
45168c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_BMAP]);
45178c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_BMAP]);
45188c2ecf20Sopenharmony_ci
45198c2ecf20Sopenharmony_ci	val64 = VXGE_HW_TIM_WRKLD_CLC_WRKLD_EVAL_PRD(150);
45208c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_TIM_WRKLD_CLC_WRKLD_EVAL_DIV(0);
45218c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_TIM_WRKLD_CLC_CNT_RX_TX(3);
45228c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->tim_wrkld_clc);
45238c2ecf20Sopenharmony_ci
45248c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
45258c2ecf20Sopenharmony_ci}
45268c2ecf20Sopenharmony_ci
45278c2ecf20Sopenharmony_ci/*
45288c2ecf20Sopenharmony_ci * __vxge_hw_vpath_initialize
45298c2ecf20Sopenharmony_ci * This routine is the final phase of init which initializes the
45308c2ecf20Sopenharmony_ci * registers of the vpath using the configuration passed.
45318c2ecf20Sopenharmony_ci */
45328c2ecf20Sopenharmony_cistatic enum vxge_hw_status
45338c2ecf20Sopenharmony_ci__vxge_hw_vpath_initialize(struct __vxge_hw_device *hldev, u32 vp_id)
45348c2ecf20Sopenharmony_ci{
45358c2ecf20Sopenharmony_ci	u64 val64;
45368c2ecf20Sopenharmony_ci	u32 val32;
45378c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
45388c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
45398c2ecf20Sopenharmony_ci	struct vxge_hw_vpath_reg __iomem *vp_reg;
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
45428c2ecf20Sopenharmony_ci
45438c2ecf20Sopenharmony_ci	if (!(hldev->vpath_assignments & vxge_mBIT(vp_id))) {
45448c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_AVAILABLE;
45458c2ecf20Sopenharmony_ci		goto exit;
45468c2ecf20Sopenharmony_ci	}
45478c2ecf20Sopenharmony_ci	vp_reg = vpath->vp_reg;
45488c2ecf20Sopenharmony_ci
45498c2ecf20Sopenharmony_ci	status =  __vxge_hw_vpath_swapper_set(vpath->vp_reg);
45508c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
45518c2ecf20Sopenharmony_ci		goto exit;
45528c2ecf20Sopenharmony_ci
45538c2ecf20Sopenharmony_ci	status =  __vxge_hw_vpath_mac_configure(hldev, vp_id);
45548c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
45558c2ecf20Sopenharmony_ci		goto exit;
45568c2ecf20Sopenharmony_ci
45578c2ecf20Sopenharmony_ci	status =  __vxge_hw_vpath_kdfc_configure(hldev, vp_id);
45588c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
45598c2ecf20Sopenharmony_ci		goto exit;
45608c2ecf20Sopenharmony_ci
45618c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_tim_configure(hldev, vp_id);
45628c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
45638c2ecf20Sopenharmony_ci		goto exit;
45648c2ecf20Sopenharmony_ci
45658c2ecf20Sopenharmony_ci	val64 = readq(&vp_reg->rtdma_rd_optimization_ctrl);
45668c2ecf20Sopenharmony_ci
45678c2ecf20Sopenharmony_ci	/* Get MRRS value from device control */
45688c2ecf20Sopenharmony_ci	status  = __vxge_hw_vpath_pci_read(vpath, 1, 0x78, &val32);
45698c2ecf20Sopenharmony_ci	if (status == VXGE_HW_OK) {
45708c2ecf20Sopenharmony_ci		val32 = (val32 & VXGE_HW_PCI_EXP_DEVCTL_READRQ) >> 12;
45718c2ecf20Sopenharmony_ci		val64 &=
45728c2ecf20Sopenharmony_ci		    ~(VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(7));
45738c2ecf20Sopenharmony_ci		val64 |=
45748c2ecf20Sopenharmony_ci		    VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_FILL_THRESH(val32);
45758c2ecf20Sopenharmony_ci
45768c2ecf20Sopenharmony_ci		val64 |= VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_WAIT_FOR_SPACE;
45778c2ecf20Sopenharmony_ci	}
45788c2ecf20Sopenharmony_ci
45798c2ecf20Sopenharmony_ci	val64 &= ~(VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(7));
45808c2ecf20Sopenharmony_ci	val64 |=
45818c2ecf20Sopenharmony_ci	    VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY(
45828c2ecf20Sopenharmony_ci		    VXGE_HW_MAX_PAYLOAD_SIZE_512);
45838c2ecf20Sopenharmony_ci
45848c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_RTDMA_RD_OPTIMIZATION_CTRL_FB_ADDR_BDRY_EN;
45858c2ecf20Sopenharmony_ci	writeq(val64, &vp_reg->rtdma_rd_optimization_ctrl);
45868c2ecf20Sopenharmony_ci
45878c2ecf20Sopenharmony_ciexit:
45888c2ecf20Sopenharmony_ci	return status;
45898c2ecf20Sopenharmony_ci}
45908c2ecf20Sopenharmony_ci
45918c2ecf20Sopenharmony_ci/*
45928c2ecf20Sopenharmony_ci * __vxge_hw_vp_terminate - Terminate Virtual Path structure
45938c2ecf20Sopenharmony_ci * This routine closes all channels it opened and freeup memory
45948c2ecf20Sopenharmony_ci */
45958c2ecf20Sopenharmony_cistatic void __vxge_hw_vp_terminate(struct __vxge_hw_device *hldev, u32 vp_id)
45968c2ecf20Sopenharmony_ci{
45978c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
45988c2ecf20Sopenharmony_ci
45998c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
46008c2ecf20Sopenharmony_ci
46018c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN)
46028c2ecf20Sopenharmony_ci		goto exit;
46038c2ecf20Sopenharmony_ci
46048c2ecf20Sopenharmony_ci	VXGE_HW_DEVICE_TIM_INT_MASK_RESET(vpath->hldev->tim_int_mask0,
46058c2ecf20Sopenharmony_ci		vpath->hldev->tim_int_mask1, vpath->vp_id);
46068c2ecf20Sopenharmony_ci	hldev->stats.hw_dev_info_stats.vpath_info[vpath->vp_id] = NULL;
46078c2ecf20Sopenharmony_ci
46088c2ecf20Sopenharmony_ci	/* If the whole struct __vxge_hw_virtualpath is zeroed, nothing will
46098c2ecf20Sopenharmony_ci	 * work after the interface is brought down.
46108c2ecf20Sopenharmony_ci	 */
46118c2ecf20Sopenharmony_ci	spin_lock(&vpath->lock);
46128c2ecf20Sopenharmony_ci	vpath->vp_open = VXGE_HW_VP_NOT_OPEN;
46138c2ecf20Sopenharmony_ci	spin_unlock(&vpath->lock);
46148c2ecf20Sopenharmony_ci
46158c2ecf20Sopenharmony_ci	vpath->vpmgmt_reg = NULL;
46168c2ecf20Sopenharmony_ci	vpath->nofl_db = NULL;
46178c2ecf20Sopenharmony_ci	vpath->max_mtu = 0;
46188c2ecf20Sopenharmony_ci	vpath->vsport_number = 0;
46198c2ecf20Sopenharmony_ci	vpath->max_kdfc_db = 0;
46208c2ecf20Sopenharmony_ci	vpath->max_nofl_db = 0;
46218c2ecf20Sopenharmony_ci	vpath->ringh = NULL;
46228c2ecf20Sopenharmony_ci	vpath->fifoh = NULL;
46238c2ecf20Sopenharmony_ci	memset(&vpath->vpath_handles, 0, sizeof(struct list_head));
46248c2ecf20Sopenharmony_ci	vpath->stats_block = NULL;
46258c2ecf20Sopenharmony_ci	vpath->hw_stats = NULL;
46268c2ecf20Sopenharmony_ci	vpath->hw_stats_sav = NULL;
46278c2ecf20Sopenharmony_ci	vpath->sw_stats = NULL;
46288c2ecf20Sopenharmony_ci
46298c2ecf20Sopenharmony_ciexit:
46308c2ecf20Sopenharmony_ci	return;
46318c2ecf20Sopenharmony_ci}
46328c2ecf20Sopenharmony_ci
46338c2ecf20Sopenharmony_ci/*
46348c2ecf20Sopenharmony_ci * __vxge_hw_vp_initialize - Initialize Virtual Path structure
46358c2ecf20Sopenharmony_ci * This routine is the initial phase of init which resets the vpath and
46368c2ecf20Sopenharmony_ci * initializes the software support structures.
46378c2ecf20Sopenharmony_ci */
46388c2ecf20Sopenharmony_cistatic enum vxge_hw_status
46398c2ecf20Sopenharmony_ci__vxge_hw_vp_initialize(struct __vxge_hw_device *hldev, u32 vp_id,
46408c2ecf20Sopenharmony_ci			struct vxge_hw_vp_config *config)
46418c2ecf20Sopenharmony_ci{
46428c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
46438c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
46448c2ecf20Sopenharmony_ci
46458c2ecf20Sopenharmony_ci	if (!(hldev->vpath_assignments & vxge_mBIT(vp_id))) {
46468c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_AVAILABLE;
46478c2ecf20Sopenharmony_ci		goto exit;
46488c2ecf20Sopenharmony_ci	}
46498c2ecf20Sopenharmony_ci
46508c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[vp_id];
46518c2ecf20Sopenharmony_ci
46528c2ecf20Sopenharmony_ci	spin_lock_init(&vpath->lock);
46538c2ecf20Sopenharmony_ci	vpath->vp_id = vp_id;
46548c2ecf20Sopenharmony_ci	vpath->vp_open = VXGE_HW_VP_OPEN;
46558c2ecf20Sopenharmony_ci	vpath->hldev = hldev;
46568c2ecf20Sopenharmony_ci	vpath->vp_config = config;
46578c2ecf20Sopenharmony_ci	vpath->vp_reg = hldev->vpath_reg[vp_id];
46588c2ecf20Sopenharmony_ci	vpath->vpmgmt_reg = hldev->vpmgmt_reg[vp_id];
46598c2ecf20Sopenharmony_ci
46608c2ecf20Sopenharmony_ci	__vxge_hw_vpath_reset(hldev, vp_id);
46618c2ecf20Sopenharmony_ci
46628c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_reset_check(vpath);
46638c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
46648c2ecf20Sopenharmony_ci		memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
46658c2ecf20Sopenharmony_ci		goto exit;
46668c2ecf20Sopenharmony_ci	}
46678c2ecf20Sopenharmony_ci
46688c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_mgmt_read(hldev, vpath);
46698c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK) {
46708c2ecf20Sopenharmony_ci		memset(vpath, 0, sizeof(struct __vxge_hw_virtualpath));
46718c2ecf20Sopenharmony_ci		goto exit;
46728c2ecf20Sopenharmony_ci	}
46738c2ecf20Sopenharmony_ci
46748c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&vpath->vpath_handles);
46758c2ecf20Sopenharmony_ci
46768c2ecf20Sopenharmony_ci	vpath->sw_stats = &hldev->stats.sw_dev_info_stats.vpath_info[vp_id];
46778c2ecf20Sopenharmony_ci
46788c2ecf20Sopenharmony_ci	VXGE_HW_DEVICE_TIM_INT_MASK_SET(hldev->tim_int_mask0,
46798c2ecf20Sopenharmony_ci		hldev->tim_int_mask1, vp_id);
46808c2ecf20Sopenharmony_ci
46818c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_initialize(hldev, vp_id);
46828c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
46838c2ecf20Sopenharmony_ci		__vxge_hw_vp_terminate(hldev, vp_id);
46848c2ecf20Sopenharmony_ciexit:
46858c2ecf20Sopenharmony_ci	return status;
46868c2ecf20Sopenharmony_ci}
46878c2ecf20Sopenharmony_ci
46888c2ecf20Sopenharmony_ci/*
46898c2ecf20Sopenharmony_ci * vxge_hw_vpath_mtu_set - Set MTU.
46908c2ecf20Sopenharmony_ci * Set new MTU value. Example, to use jumbo frames:
46918c2ecf20Sopenharmony_ci * vxge_hw_vpath_mtu_set(my_device, 9600);
46928c2ecf20Sopenharmony_ci */
46938c2ecf20Sopenharmony_cienum vxge_hw_status
46948c2ecf20Sopenharmony_civxge_hw_vpath_mtu_set(struct __vxge_hw_vpath_handle *vp, u32 new_mtu)
46958c2ecf20Sopenharmony_ci{
46968c2ecf20Sopenharmony_ci	u64 val64;
46978c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
46988c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
46998c2ecf20Sopenharmony_ci
47008c2ecf20Sopenharmony_ci	if (vp == NULL) {
47018c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_HANDLE;
47028c2ecf20Sopenharmony_ci		goto exit;
47038c2ecf20Sopenharmony_ci	}
47048c2ecf20Sopenharmony_ci	vpath = vp->vpath;
47058c2ecf20Sopenharmony_ci
47068c2ecf20Sopenharmony_ci	new_mtu += VXGE_HW_MAC_HEADER_MAX_SIZE;
47078c2ecf20Sopenharmony_ci
47088c2ecf20Sopenharmony_ci	if ((new_mtu < VXGE_HW_MIN_MTU) || (new_mtu > vpath->max_mtu))
47098c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_MTU_SIZE;
47108c2ecf20Sopenharmony_ci
47118c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
47128c2ecf20Sopenharmony_ci
47138c2ecf20Sopenharmony_ci	val64 &= ~VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(0x3fff);
47148c2ecf20Sopenharmony_ci	val64 |= VXGE_HW_RXMAC_VCFG0_RTS_MAX_FRM_LEN(new_mtu);
47158c2ecf20Sopenharmony_ci
47168c2ecf20Sopenharmony_ci	writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
47178c2ecf20Sopenharmony_ci
47188c2ecf20Sopenharmony_ci	vpath->vp_config->mtu = new_mtu - VXGE_HW_MAC_HEADER_MAX_SIZE;
47198c2ecf20Sopenharmony_ci
47208c2ecf20Sopenharmony_ciexit:
47218c2ecf20Sopenharmony_ci	return status;
47228c2ecf20Sopenharmony_ci}
47238c2ecf20Sopenharmony_ci
47248c2ecf20Sopenharmony_ci/*
47258c2ecf20Sopenharmony_ci * vxge_hw_vpath_stats_enable - Enable vpath h/wstatistics.
47268c2ecf20Sopenharmony_ci * Enable the DMA vpath statistics. The function is to be called to re-enable
47278c2ecf20Sopenharmony_ci * the adapter to update stats into the host memory
47288c2ecf20Sopenharmony_ci */
47298c2ecf20Sopenharmony_cistatic enum vxge_hw_status
47308c2ecf20Sopenharmony_civxge_hw_vpath_stats_enable(struct __vxge_hw_vpath_handle *vp)
47318c2ecf20Sopenharmony_ci{
47328c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
47338c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
47348c2ecf20Sopenharmony_ci
47358c2ecf20Sopenharmony_ci	vpath = vp->vpath;
47368c2ecf20Sopenharmony_ci
47378c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
47388c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
47398c2ecf20Sopenharmony_ci		goto exit;
47408c2ecf20Sopenharmony_ci	}
47418c2ecf20Sopenharmony_ci
47428c2ecf20Sopenharmony_ci	memcpy(vpath->hw_stats_sav, vpath->hw_stats,
47438c2ecf20Sopenharmony_ci			sizeof(struct vxge_hw_vpath_stats_hw_info));
47448c2ecf20Sopenharmony_ci
47458c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_stats_get(vpath, vpath->hw_stats);
47468c2ecf20Sopenharmony_ciexit:
47478c2ecf20Sopenharmony_ci	return status;
47488c2ecf20Sopenharmony_ci}
47498c2ecf20Sopenharmony_ci
47508c2ecf20Sopenharmony_ci/*
47518c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_block_allocate - Allocates a block from block pool
47528c2ecf20Sopenharmony_ci * This function allocates a block from block pool or from the system
47538c2ecf20Sopenharmony_ci */
47548c2ecf20Sopenharmony_cistatic struct __vxge_hw_blockpool_entry *
47558c2ecf20Sopenharmony_ci__vxge_hw_blockpool_block_allocate(struct __vxge_hw_device *devh, u32 size)
47568c2ecf20Sopenharmony_ci{
47578c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool_entry *entry = NULL;
47588c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool  *blockpool;
47598c2ecf20Sopenharmony_ci
47608c2ecf20Sopenharmony_ci	blockpool = &devh->block_pool;
47618c2ecf20Sopenharmony_ci
47628c2ecf20Sopenharmony_ci	if (size == blockpool->block_size) {
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_ci		if (!list_empty(&blockpool->free_block_list))
47658c2ecf20Sopenharmony_ci			entry = (struct __vxge_hw_blockpool_entry *)
47668c2ecf20Sopenharmony_ci				list_first_entry(&blockpool->free_block_list,
47678c2ecf20Sopenharmony_ci					struct __vxge_hw_blockpool_entry,
47688c2ecf20Sopenharmony_ci					item);
47698c2ecf20Sopenharmony_ci
47708c2ecf20Sopenharmony_ci		if (entry != NULL) {
47718c2ecf20Sopenharmony_ci			list_del(&entry->item);
47728c2ecf20Sopenharmony_ci			blockpool->pool_size--;
47738c2ecf20Sopenharmony_ci		}
47748c2ecf20Sopenharmony_ci	}
47758c2ecf20Sopenharmony_ci
47768c2ecf20Sopenharmony_ci	if (entry != NULL)
47778c2ecf20Sopenharmony_ci		__vxge_hw_blockpool_blocks_add(blockpool);
47788c2ecf20Sopenharmony_ci
47798c2ecf20Sopenharmony_ci	return entry;
47808c2ecf20Sopenharmony_ci}
47818c2ecf20Sopenharmony_ci
47828c2ecf20Sopenharmony_ci/*
47838c2ecf20Sopenharmony_ci * vxge_hw_vpath_open - Open a virtual path on a given adapter
47848c2ecf20Sopenharmony_ci * This function is used to open access to virtual path of an
47858c2ecf20Sopenharmony_ci * adapter for offload, GRO operations. This function returns
47868c2ecf20Sopenharmony_ci * synchronously.
47878c2ecf20Sopenharmony_ci */
47888c2ecf20Sopenharmony_cienum vxge_hw_status
47898c2ecf20Sopenharmony_civxge_hw_vpath_open(struct __vxge_hw_device *hldev,
47908c2ecf20Sopenharmony_ci		   struct vxge_hw_vpath_attr *attr,
47918c2ecf20Sopenharmony_ci		   struct __vxge_hw_vpath_handle **vpath_handle)
47928c2ecf20Sopenharmony_ci{
47938c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath;
47948c2ecf20Sopenharmony_ci	struct __vxge_hw_vpath_handle *vp;
47958c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
47968c2ecf20Sopenharmony_ci
47978c2ecf20Sopenharmony_ci	vpath = &hldev->virtual_paths[attr->vp_id];
47988c2ecf20Sopenharmony_ci
47998c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_OPEN) {
48008c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_INVALID_STATE;
48018c2ecf20Sopenharmony_ci		goto vpath_open_exit1;
48028c2ecf20Sopenharmony_ci	}
48038c2ecf20Sopenharmony_ci
48048c2ecf20Sopenharmony_ci	status = __vxge_hw_vp_initialize(hldev, attr->vp_id,
48058c2ecf20Sopenharmony_ci			&hldev->config.vp_config[attr->vp_id]);
48068c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
48078c2ecf20Sopenharmony_ci		goto vpath_open_exit1;
48088c2ecf20Sopenharmony_ci
48098c2ecf20Sopenharmony_ci	vp = vzalloc(sizeof(struct __vxge_hw_vpath_handle));
48108c2ecf20Sopenharmony_ci	if (vp == NULL) {
48118c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
48128c2ecf20Sopenharmony_ci		goto vpath_open_exit2;
48138c2ecf20Sopenharmony_ci	}
48148c2ecf20Sopenharmony_ci
48158c2ecf20Sopenharmony_ci	vp->vpath = vpath;
48168c2ecf20Sopenharmony_ci
48178c2ecf20Sopenharmony_ci	if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
48188c2ecf20Sopenharmony_ci		status = __vxge_hw_fifo_create(vp, &attr->fifo_attr);
48198c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
48208c2ecf20Sopenharmony_ci			goto vpath_open_exit6;
48218c2ecf20Sopenharmony_ci	}
48228c2ecf20Sopenharmony_ci
48238c2ecf20Sopenharmony_ci	if (vpath->vp_config->ring.enable == VXGE_HW_RING_ENABLE) {
48248c2ecf20Sopenharmony_ci		status = __vxge_hw_ring_create(vp, &attr->ring_attr);
48258c2ecf20Sopenharmony_ci		if (status != VXGE_HW_OK)
48268c2ecf20Sopenharmony_ci			goto vpath_open_exit7;
48278c2ecf20Sopenharmony_ci
48288c2ecf20Sopenharmony_ci		__vxge_hw_vpath_prc_configure(hldev, attr->vp_id);
48298c2ecf20Sopenharmony_ci	}
48308c2ecf20Sopenharmony_ci
48318c2ecf20Sopenharmony_ci	vpath->fifoh->tx_intr_num =
48328c2ecf20Sopenharmony_ci		(attr->vp_id * VXGE_HW_MAX_INTR_PER_VP)  +
48338c2ecf20Sopenharmony_ci			VXGE_HW_VPATH_INTR_TX;
48348c2ecf20Sopenharmony_ci
48358c2ecf20Sopenharmony_ci	vpath->stats_block = __vxge_hw_blockpool_block_allocate(hldev,
48368c2ecf20Sopenharmony_ci				VXGE_HW_BLOCK_SIZE);
48378c2ecf20Sopenharmony_ci	if (vpath->stats_block == NULL) {
48388c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_OUT_OF_MEMORY;
48398c2ecf20Sopenharmony_ci		goto vpath_open_exit8;
48408c2ecf20Sopenharmony_ci	}
48418c2ecf20Sopenharmony_ci
48428c2ecf20Sopenharmony_ci	vpath->hw_stats = vpath->stats_block->memblock;
48438c2ecf20Sopenharmony_ci	memset(vpath->hw_stats, 0,
48448c2ecf20Sopenharmony_ci		sizeof(struct vxge_hw_vpath_stats_hw_info));
48458c2ecf20Sopenharmony_ci
48468c2ecf20Sopenharmony_ci	hldev->stats.hw_dev_info_stats.vpath_info[attr->vp_id] =
48478c2ecf20Sopenharmony_ci						vpath->hw_stats;
48488c2ecf20Sopenharmony_ci
48498c2ecf20Sopenharmony_ci	vpath->hw_stats_sav =
48508c2ecf20Sopenharmony_ci		&hldev->stats.hw_dev_info_stats.vpath_info_sav[attr->vp_id];
48518c2ecf20Sopenharmony_ci	memset(vpath->hw_stats_sav, 0,
48528c2ecf20Sopenharmony_ci			sizeof(struct vxge_hw_vpath_stats_hw_info));
48538c2ecf20Sopenharmony_ci
48548c2ecf20Sopenharmony_ci	writeq(vpath->stats_block->dma_addr, &vpath->vp_reg->stats_cfg);
48558c2ecf20Sopenharmony_ci
48568c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_stats_enable(vp);
48578c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
48588c2ecf20Sopenharmony_ci		goto vpath_open_exit8;
48598c2ecf20Sopenharmony_ci
48608c2ecf20Sopenharmony_ci	list_add(&vp->item, &vpath->vpath_handles);
48618c2ecf20Sopenharmony_ci
48628c2ecf20Sopenharmony_ci	hldev->vpaths_deployed |= vxge_mBIT(vpath->vp_id);
48638c2ecf20Sopenharmony_ci
48648c2ecf20Sopenharmony_ci	*vpath_handle = vp;
48658c2ecf20Sopenharmony_ci
48668c2ecf20Sopenharmony_ci	attr->fifo_attr.userdata = vpath->fifoh;
48678c2ecf20Sopenharmony_ci	attr->ring_attr.userdata = vpath->ringh;
48688c2ecf20Sopenharmony_ci
48698c2ecf20Sopenharmony_ci	return VXGE_HW_OK;
48708c2ecf20Sopenharmony_ci
48718c2ecf20Sopenharmony_civpath_open_exit8:
48728c2ecf20Sopenharmony_ci	if (vpath->ringh != NULL)
48738c2ecf20Sopenharmony_ci		__vxge_hw_ring_delete(vp);
48748c2ecf20Sopenharmony_civpath_open_exit7:
48758c2ecf20Sopenharmony_ci	if (vpath->fifoh != NULL)
48768c2ecf20Sopenharmony_ci		__vxge_hw_fifo_delete(vp);
48778c2ecf20Sopenharmony_civpath_open_exit6:
48788c2ecf20Sopenharmony_ci	vfree(vp);
48798c2ecf20Sopenharmony_civpath_open_exit2:
48808c2ecf20Sopenharmony_ci	__vxge_hw_vp_terminate(hldev, attr->vp_id);
48818c2ecf20Sopenharmony_civpath_open_exit1:
48828c2ecf20Sopenharmony_ci
48838c2ecf20Sopenharmony_ci	return status;
48848c2ecf20Sopenharmony_ci}
48858c2ecf20Sopenharmony_ci
48868c2ecf20Sopenharmony_ci/**
48878c2ecf20Sopenharmony_ci * vxge_hw_vpath_rx_doorbell_post - Close the handle got from previous vpath
48888c2ecf20Sopenharmony_ci * (vpath) open
48898c2ecf20Sopenharmony_ci * @vp: Handle got from previous vpath open
48908c2ecf20Sopenharmony_ci *
48918c2ecf20Sopenharmony_ci * This function is used to close access to virtual path opened
48928c2ecf20Sopenharmony_ci * earlier.
48938c2ecf20Sopenharmony_ci */
48948c2ecf20Sopenharmony_civoid vxge_hw_vpath_rx_doorbell_init(struct __vxge_hw_vpath_handle *vp)
48958c2ecf20Sopenharmony_ci{
48968c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath = vp->vpath;
48978c2ecf20Sopenharmony_ci	struct __vxge_hw_ring *ring = vpath->ringh;
48988c2ecf20Sopenharmony_ci	struct vxgedev *vdev = netdev_priv(vpath->hldev->ndev);
48998c2ecf20Sopenharmony_ci	u64 new_count, val64, val164;
49008c2ecf20Sopenharmony_ci
49018c2ecf20Sopenharmony_ci	if (vdev->titan1) {
49028c2ecf20Sopenharmony_ci		new_count = readq(&vpath->vp_reg->rxdmem_size);
49038c2ecf20Sopenharmony_ci		new_count &= 0x1fff;
49048c2ecf20Sopenharmony_ci	} else
49058c2ecf20Sopenharmony_ci		new_count = ring->config->ring_blocks * VXGE_HW_BLOCK_SIZE / 8;
49068c2ecf20Sopenharmony_ci
49078c2ecf20Sopenharmony_ci	val164 = VXGE_HW_RXDMEM_SIZE_PRC_RXDMEM_SIZE(new_count);
49088c2ecf20Sopenharmony_ci
49098c2ecf20Sopenharmony_ci	writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(val164),
49108c2ecf20Sopenharmony_ci		&vpath->vp_reg->prc_rxd_doorbell);
49118c2ecf20Sopenharmony_ci	readl(&vpath->vp_reg->prc_rxd_doorbell);
49128c2ecf20Sopenharmony_ci
49138c2ecf20Sopenharmony_ci	val164 /= 2;
49148c2ecf20Sopenharmony_ci	val64 = readq(&vpath->vp_reg->prc_cfg6);
49158c2ecf20Sopenharmony_ci	val64 = VXGE_HW_PRC_CFG6_RXD_SPAT(val64);
49168c2ecf20Sopenharmony_ci	val64 &= 0x1ff;
49178c2ecf20Sopenharmony_ci
49188c2ecf20Sopenharmony_ci	/*
49198c2ecf20Sopenharmony_ci	 * Each RxD is of 4 qwords
49208c2ecf20Sopenharmony_ci	 */
49218c2ecf20Sopenharmony_ci	new_count -= (val64 + 1);
49228c2ecf20Sopenharmony_ci	val64 = min(val164, new_count) / 4;
49238c2ecf20Sopenharmony_ci
49248c2ecf20Sopenharmony_ci	ring->rxds_limit = min(ring->rxds_limit, val64);
49258c2ecf20Sopenharmony_ci	if (ring->rxds_limit < 4)
49268c2ecf20Sopenharmony_ci		ring->rxds_limit = 4;
49278c2ecf20Sopenharmony_ci}
49288c2ecf20Sopenharmony_ci
49298c2ecf20Sopenharmony_ci/*
49308c2ecf20Sopenharmony_ci * __vxge_hw_blockpool_block_free - Frees a block from block pool
49318c2ecf20Sopenharmony_ci * @devh: Hal device
49328c2ecf20Sopenharmony_ci * @entry: Entry of block to be freed
49338c2ecf20Sopenharmony_ci *
49348c2ecf20Sopenharmony_ci * This function frees a block from block pool
49358c2ecf20Sopenharmony_ci */
49368c2ecf20Sopenharmony_cistatic void
49378c2ecf20Sopenharmony_ci__vxge_hw_blockpool_block_free(struct __vxge_hw_device *devh,
49388c2ecf20Sopenharmony_ci			       struct __vxge_hw_blockpool_entry *entry)
49398c2ecf20Sopenharmony_ci{
49408c2ecf20Sopenharmony_ci	struct __vxge_hw_blockpool  *blockpool;
49418c2ecf20Sopenharmony_ci
49428c2ecf20Sopenharmony_ci	blockpool = &devh->block_pool;
49438c2ecf20Sopenharmony_ci
49448c2ecf20Sopenharmony_ci	if (entry->length == blockpool->block_size) {
49458c2ecf20Sopenharmony_ci		list_add(&entry->item, &blockpool->free_block_list);
49468c2ecf20Sopenharmony_ci		blockpool->pool_size++;
49478c2ecf20Sopenharmony_ci	}
49488c2ecf20Sopenharmony_ci
49498c2ecf20Sopenharmony_ci	__vxge_hw_blockpool_blocks_remove(blockpool);
49508c2ecf20Sopenharmony_ci}
49518c2ecf20Sopenharmony_ci
49528c2ecf20Sopenharmony_ci/*
49538c2ecf20Sopenharmony_ci * vxge_hw_vpath_close - Close the handle got from previous vpath (vpath) open
49548c2ecf20Sopenharmony_ci * This function is used to close access to virtual path opened
49558c2ecf20Sopenharmony_ci * earlier.
49568c2ecf20Sopenharmony_ci */
49578c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_close(struct __vxge_hw_vpath_handle *vp)
49588c2ecf20Sopenharmony_ci{
49598c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath = NULL;
49608c2ecf20Sopenharmony_ci	struct __vxge_hw_device *devh = NULL;
49618c2ecf20Sopenharmony_ci	u32 vp_id = vp->vpath->vp_id;
49628c2ecf20Sopenharmony_ci	u32 is_empty = TRUE;
49638c2ecf20Sopenharmony_ci	enum vxge_hw_status status = VXGE_HW_OK;
49648c2ecf20Sopenharmony_ci
49658c2ecf20Sopenharmony_ci	vpath = vp->vpath;
49668c2ecf20Sopenharmony_ci	devh = vpath->hldev;
49678c2ecf20Sopenharmony_ci
49688c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
49698c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
49708c2ecf20Sopenharmony_ci		goto vpath_close_exit;
49718c2ecf20Sopenharmony_ci	}
49728c2ecf20Sopenharmony_ci
49738c2ecf20Sopenharmony_ci	list_del(&vp->item);
49748c2ecf20Sopenharmony_ci
49758c2ecf20Sopenharmony_ci	if (!list_empty(&vpath->vpath_handles)) {
49768c2ecf20Sopenharmony_ci		list_add(&vp->item, &vpath->vpath_handles);
49778c2ecf20Sopenharmony_ci		is_empty = FALSE;
49788c2ecf20Sopenharmony_ci	}
49798c2ecf20Sopenharmony_ci
49808c2ecf20Sopenharmony_ci	if (!is_empty) {
49818c2ecf20Sopenharmony_ci		status = VXGE_HW_FAIL;
49828c2ecf20Sopenharmony_ci		goto vpath_close_exit;
49838c2ecf20Sopenharmony_ci	}
49848c2ecf20Sopenharmony_ci
49858c2ecf20Sopenharmony_ci	devh->vpaths_deployed &= ~vxge_mBIT(vp_id);
49868c2ecf20Sopenharmony_ci
49878c2ecf20Sopenharmony_ci	if (vpath->ringh != NULL)
49888c2ecf20Sopenharmony_ci		__vxge_hw_ring_delete(vp);
49898c2ecf20Sopenharmony_ci
49908c2ecf20Sopenharmony_ci	if (vpath->fifoh != NULL)
49918c2ecf20Sopenharmony_ci		__vxge_hw_fifo_delete(vp);
49928c2ecf20Sopenharmony_ci
49938c2ecf20Sopenharmony_ci	if (vpath->stats_block != NULL)
49948c2ecf20Sopenharmony_ci		__vxge_hw_blockpool_block_free(devh, vpath->stats_block);
49958c2ecf20Sopenharmony_ci
49968c2ecf20Sopenharmony_ci	vfree(vp);
49978c2ecf20Sopenharmony_ci
49988c2ecf20Sopenharmony_ci	__vxge_hw_vp_terminate(devh, vp_id);
49998c2ecf20Sopenharmony_ci
50008c2ecf20Sopenharmony_civpath_close_exit:
50018c2ecf20Sopenharmony_ci	return status;
50028c2ecf20Sopenharmony_ci}
50038c2ecf20Sopenharmony_ci
50048c2ecf20Sopenharmony_ci/*
50058c2ecf20Sopenharmony_ci * vxge_hw_vpath_reset - Resets vpath
50068c2ecf20Sopenharmony_ci * This function is used to request a reset of vpath
50078c2ecf20Sopenharmony_ci */
50088c2ecf20Sopenharmony_cienum vxge_hw_status vxge_hw_vpath_reset(struct __vxge_hw_vpath_handle *vp)
50098c2ecf20Sopenharmony_ci{
50108c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
50118c2ecf20Sopenharmony_ci	u32 vp_id;
50128c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath = vp->vpath;
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_ci	vp_id = vpath->vp_id;
50158c2ecf20Sopenharmony_ci
50168c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
50178c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
50188c2ecf20Sopenharmony_ci		goto exit;
50198c2ecf20Sopenharmony_ci	}
50208c2ecf20Sopenharmony_ci
50218c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_reset(vpath->hldev, vp_id);
50228c2ecf20Sopenharmony_ci	if (status == VXGE_HW_OK)
50238c2ecf20Sopenharmony_ci		vpath->sw_stats->soft_reset_cnt++;
50248c2ecf20Sopenharmony_ciexit:
50258c2ecf20Sopenharmony_ci	return status;
50268c2ecf20Sopenharmony_ci}
50278c2ecf20Sopenharmony_ci
50288c2ecf20Sopenharmony_ci/*
50298c2ecf20Sopenharmony_ci * vxge_hw_vpath_recover_from_reset - Poll for reset complete and re-initialize.
50308c2ecf20Sopenharmony_ci * This function poll's for the vpath reset completion and re initializes
50318c2ecf20Sopenharmony_ci * the vpath.
50328c2ecf20Sopenharmony_ci */
50338c2ecf20Sopenharmony_cienum vxge_hw_status
50348c2ecf20Sopenharmony_civxge_hw_vpath_recover_from_reset(struct __vxge_hw_vpath_handle *vp)
50358c2ecf20Sopenharmony_ci{
50368c2ecf20Sopenharmony_ci	struct __vxge_hw_virtualpath *vpath = NULL;
50378c2ecf20Sopenharmony_ci	enum vxge_hw_status status;
50388c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev;
50398c2ecf20Sopenharmony_ci	u32 vp_id;
50408c2ecf20Sopenharmony_ci
50418c2ecf20Sopenharmony_ci	vp_id = vp->vpath->vp_id;
50428c2ecf20Sopenharmony_ci	vpath = vp->vpath;
50438c2ecf20Sopenharmony_ci	hldev = vpath->hldev;
50448c2ecf20Sopenharmony_ci
50458c2ecf20Sopenharmony_ci	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
50468c2ecf20Sopenharmony_ci		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
50478c2ecf20Sopenharmony_ci		goto exit;
50488c2ecf20Sopenharmony_ci	}
50498c2ecf20Sopenharmony_ci
50508c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_reset_check(vpath);
50518c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
50528c2ecf20Sopenharmony_ci		goto exit;
50538c2ecf20Sopenharmony_ci
50548c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_sw_reset(hldev, vp_id);
50558c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
50568c2ecf20Sopenharmony_ci		goto exit;
50578c2ecf20Sopenharmony_ci
50588c2ecf20Sopenharmony_ci	status = __vxge_hw_vpath_initialize(hldev, vp_id);
50598c2ecf20Sopenharmony_ci	if (status != VXGE_HW_OK)
50608c2ecf20Sopenharmony_ci		goto exit;
50618c2ecf20Sopenharmony_ci
50628c2ecf20Sopenharmony_ci	if (vpath->ringh != NULL)
50638c2ecf20Sopenharmony_ci		__vxge_hw_vpath_prc_configure(hldev, vp_id);
50648c2ecf20Sopenharmony_ci
50658c2ecf20Sopenharmony_ci	memset(vpath->hw_stats, 0,
50668c2ecf20Sopenharmony_ci		sizeof(struct vxge_hw_vpath_stats_hw_info));
50678c2ecf20Sopenharmony_ci
50688c2ecf20Sopenharmony_ci	memset(vpath->hw_stats_sav, 0,
50698c2ecf20Sopenharmony_ci		sizeof(struct vxge_hw_vpath_stats_hw_info));
50708c2ecf20Sopenharmony_ci
50718c2ecf20Sopenharmony_ci	writeq(vpath->stats_block->dma_addr,
50728c2ecf20Sopenharmony_ci		&vpath->vp_reg->stats_cfg);
50738c2ecf20Sopenharmony_ci
50748c2ecf20Sopenharmony_ci	status = vxge_hw_vpath_stats_enable(vp);
50758c2ecf20Sopenharmony_ci
50768c2ecf20Sopenharmony_ciexit:
50778c2ecf20Sopenharmony_ci	return status;
50788c2ecf20Sopenharmony_ci}
50798c2ecf20Sopenharmony_ci
50808c2ecf20Sopenharmony_ci/*
50818c2ecf20Sopenharmony_ci * vxge_hw_vpath_enable - Enable vpath.
50828c2ecf20Sopenharmony_ci * This routine clears the vpath reset thereby enabling a vpath
50838c2ecf20Sopenharmony_ci * to start forwarding frames and generating interrupts.
50848c2ecf20Sopenharmony_ci */
50858c2ecf20Sopenharmony_civoid
50868c2ecf20Sopenharmony_civxge_hw_vpath_enable(struct __vxge_hw_vpath_handle *vp)
50878c2ecf20Sopenharmony_ci{
50888c2ecf20Sopenharmony_ci	struct __vxge_hw_device *hldev;
50898c2ecf20Sopenharmony_ci	u64 val64;
50908c2ecf20Sopenharmony_ci
50918c2ecf20Sopenharmony_ci	hldev = vp->vpath->hldev;
50928c2ecf20Sopenharmony_ci
50938c2ecf20Sopenharmony_ci	val64 = VXGE_HW_CMN_RSTHDLR_CFG1_CLR_VPATH_RESET(
50948c2ecf20Sopenharmony_ci		1 << (16 - vp->vpath->vp_id));
50958c2ecf20Sopenharmony_ci
50968c2ecf20Sopenharmony_ci	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
50978c2ecf20Sopenharmony_ci		&hldev->common_reg->cmn_rsthdlr_cfg1);
50988c2ecf20Sopenharmony_ci}
5099