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