1171095Ssam/*- 2171095Ssam * Copyright (c) 2002-2007 Neterion, Inc. 3171095Ssam * All rights reserved. 4171095Ssam * 5171095Ssam * Redistribution and use in source and binary forms, with or without 6171095Ssam * modification, are permitted provided that the following conditions 7171095Ssam * are met: 8171095Ssam * 1. Redistributions of source code must retain the above copyright 9171095Ssam * notice, this list of conditions and the following disclaimer. 10171095Ssam * 2. Redistributions in binary form must reproduce the above copyright 11171095Ssam * notice, this list of conditions and the following disclaimer in the 12171095Ssam * documentation and/or other materials provided with the distribution. 13171095Ssam * 14171095Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15171095Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16171095Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17171095Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18171095Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19171095Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20171095Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21171095Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22171095Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23171095Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24171095Ssam * SUCH DAMAGE. 25171095Ssam * 26171095Ssam * $FreeBSD$ 27171095Ssam */ 28171095Ssam 29171095Ssam#include <dev/nxge/include/xgehal-device.h> 30171095Ssam#include <dev/nxge/include/xgehal-channel.h> 31171095Ssam#include <dev/nxge/include/xgehal-fifo.h> 32171095Ssam#include <dev/nxge/include/xgehal-ring.h> 33171095Ssam#include <dev/nxge/include/xgehal-driver.h> 34171095Ssam#include <dev/nxge/include/xgehal-mgmt.h> 35171095Ssam 36173139Srwatson#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL 37173139Srwatson#define END_SIGN 0x0 38171095Ssam 39171095Ssam#ifdef XGE_HAL_HERC_EMULATION 40171095Ssam#undef XGE_HAL_PROCESS_LINK_INT_IN_ISR 41171095Ssam#endif 42171095Ssam 43171095Ssam/* 44171095Ssam * Jenkins hash key length(in bytes) 45171095Ssam */ 46171095Ssam#define XGE_HAL_JHASH_MSG_LEN 50 47171095Ssam 48171095Ssam/* 49171095Ssam * mix(a,b,c) used in Jenkins hash algorithm 50171095Ssam */ 51171095Ssam#define mix(a,b,c) { \ 52171095Ssam a -= b; a -= c; a ^= (c>>13); \ 53171095Ssam b -= c; b -= a; b ^= (a<<8); \ 54171095Ssam c -= a; c -= b; c ^= (b>>13); \ 55171095Ssam a -= b; a -= c; a ^= (c>>12); \ 56171095Ssam b -= c; b -= a; b ^= (a<<16); \ 57171095Ssam c -= a; c -= b; c ^= (b>>5); \ 58171095Ssam a -= b; a -= c; a ^= (c>>3); \ 59171095Ssam b -= c; b -= a; b ^= (a<<10); \ 60171095Ssam c -= a; c -= b; c ^= (b>>15); \ 61171095Ssam} 62171095Ssam 63171095Ssam 64171095Ssam/* 65171095Ssam * __hal_device_event_queued 66171095Ssam * @data: pointer to xge_hal_device_t structure 67171095Ssam * 68171095Ssam * Will be called when new event succesfully queued. 69171095Ssam */ 70171095Ssamvoid 71171095Ssam__hal_device_event_queued(void *data, int event_type) 72171095Ssam{ 73171095Ssam xge_assert(((xge_hal_device_t*)data)->magic == XGE_HAL_MAGIC); 74171095Ssam if (g_xge_hal_driver->uld_callbacks.event_queued) { 75173139Srwatson g_xge_hal_driver->uld_callbacks.event_queued(data, event_type); 76171095Ssam } 77171095Ssam} 78171095Ssam 79171095Ssam/* 80171095Ssam * __hal_pio_mem_write32_upper 81171095Ssam * 82171095Ssam * Endiann-aware implementation of xge_os_pio_mem_write32(). 83171095Ssam * Since Xframe has 64bit registers, we differintiate uppper and lower 84171095Ssam * parts. 85171095Ssam */ 86171095Ssamvoid 87171095Ssam__hal_pio_mem_write32_upper(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr) 88171095Ssam{ 89171095Ssam#if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) 90171095Ssam xge_os_pio_mem_write32(pdev, regh, val, addr); 91171095Ssam#else 92171095Ssam xge_os_pio_mem_write32(pdev, regh, val, (void *)((char *)addr + 4)); 93171095Ssam#endif 94171095Ssam} 95171095Ssam 96171095Ssam/* 97171095Ssam * __hal_pio_mem_write32_upper 98171095Ssam * 99171095Ssam * Endiann-aware implementation of xge_os_pio_mem_write32(). 100171095Ssam * Since Xframe has 64bit registers, we differintiate uppper and lower 101171095Ssam * parts. 102171095Ssam */ 103171095Ssamvoid 104171095Ssam__hal_pio_mem_write32_lower(pci_dev_h pdev, pci_reg_h regh, u32 val, 105173139Srwatson void *addr) 106171095Ssam{ 107171095Ssam#if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) 108171095Ssam xge_os_pio_mem_write32(pdev, regh, val, 109173139Srwatson (void *) ((char *)addr + 4)); 110171095Ssam#else 111171095Ssam xge_os_pio_mem_write32(pdev, regh, val, addr); 112171095Ssam#endif 113171095Ssam} 114171095Ssam 115171095Ssam/* 116171095Ssam * __hal_device_register_poll 117171095Ssam * @hldev: pointer to xge_hal_device_t structure 118171095Ssam * @reg: register to poll for 119171095Ssam * @op: 0 - bit reset, 1 - bit set 120171095Ssam * @mask: mask for logical "and" condition based on %op 121171095Ssam * @max_millis: maximum time to try to poll in milliseconds 122171095Ssam * 123171095Ssam * Will poll certain register for specified amount of time. 124171095Ssam * Will poll until masked bit is not cleared. 125171095Ssam */ 126171095Ssamxge_hal_status_e 127171095Ssam__hal_device_register_poll(xge_hal_device_t *hldev, u64 *reg, 128173139Srwatson int op, u64 mask, int max_millis) 129171095Ssam{ 130171095Ssam u64 val64; 131171095Ssam int i = 0; 132171095Ssam xge_hal_status_e ret = XGE_HAL_FAIL; 133171095Ssam 134171095Ssam xge_os_udelay(10); 135171095Ssam 136171095Ssam do { 137173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg); 138173139Srwatson if (op == 0 && !(val64 & mask)) 139173139Srwatson return XGE_HAL_OK; 140173139Srwatson else if (op == 1 && (val64 & mask) == mask) 141173139Srwatson return XGE_HAL_OK; 142173139Srwatson xge_os_udelay(100); 143171095Ssam } while (++i <= 9); 144171095Ssam 145171095Ssam do { 146173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg); 147173139Srwatson if (op == 0 && !(val64 & mask)) 148173139Srwatson return XGE_HAL_OK; 149173139Srwatson else if (op == 1 && (val64 & mask) == mask) 150173139Srwatson return XGE_HAL_OK; 151173139Srwatson xge_os_udelay(1000); 152171095Ssam } while (++i < max_millis); 153171095Ssam 154171095Ssam return ret; 155171095Ssam} 156171095Ssam 157171095Ssam/* 158171095Ssam * __hal_device_wait_quiescent 159171095Ssam * @hldev: the device 160171095Ssam * @hw_status: hw_status in case of error 161171095Ssam * 162171095Ssam * Will wait until device is quiescent for some blocks. 163171095Ssam */ 164171095Ssamstatic xge_hal_status_e 165171095Ssam__hal_device_wait_quiescent(xge_hal_device_t *hldev, u64 *hw_status) 166171095Ssam{ 167171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 168171095Ssam 169171095Ssam /* poll and wait first */ 170171095Ssam#ifdef XGE_HAL_HERC_EMULATION 171171095Ssam (void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1, 172173139Srwatson (XGE_HAL_ADAPTER_STATUS_TDMA_READY | 173173139Srwatson XGE_HAL_ADAPTER_STATUS_RDMA_READY | 174173139Srwatson XGE_HAL_ADAPTER_STATUS_PFC_READY | 175173139Srwatson XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY | 176173139Srwatson XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT | 177173139Srwatson XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY | 178173139Srwatson XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY | 179173139Srwatson XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK), 180173139Srwatson XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS); 181171095Ssam#else 182171095Ssam (void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1, 183173139Srwatson (XGE_HAL_ADAPTER_STATUS_TDMA_READY | 184173139Srwatson XGE_HAL_ADAPTER_STATUS_RDMA_READY | 185173139Srwatson XGE_HAL_ADAPTER_STATUS_PFC_READY | 186173139Srwatson XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY | 187173139Srwatson XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT | 188173139Srwatson XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY | 189173139Srwatson XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY | 190173139Srwatson XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK | 191173139Srwatson XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK), 192173139Srwatson XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS); 193171095Ssam#endif 194171095Ssam 195171095Ssam return xge_hal_device_status(hldev, hw_status); 196171095Ssam} 197171095Ssam 198171095Ssam/** 199171095Ssam * xge_hal_device_is_slot_freeze 200171095Ssam * @devh: the device 201171095Ssam * 202171095Ssam * Returns non-zero if the slot is freezed. 203171095Ssam * The determination is made based on the adapter_status 204171095Ssam * register which will never give all FFs, unless PCI read 205171095Ssam * cannot go through. 206171095Ssam */ 207171095Ssamint 208171095Ssamxge_hal_device_is_slot_freeze(xge_hal_device_h devh) 209171095Ssam{ 210171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 211171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 212171095Ssam u16 device_id; 213171095Ssam u64 adapter_status = 214173139Srwatson xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 215173139Srwatson &bar0->adapter_status); 216171095Ssam xge_os_pci_read16(hldev->pdev,hldev->cfgh, 217173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, device_id), 218173139Srwatson &device_id); 219171095Ssam#ifdef TX_DEBUG 220171095Ssam if (adapter_status == XGE_HAL_ALL_FOXES) 221171095Ssam { 222173139Srwatson u64 dummy; 223173139Srwatson dummy = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 224173139Srwatson &bar0->pcc_enable); 225173139Srwatson printf(">>> Slot is frozen!\n"); 226173139Srwatson brkpoint(0); 227171095Ssam } 228171095Ssam#endif 229171095Ssam return((adapter_status == XGE_HAL_ALL_FOXES) || (device_id == 0xffff)); 230171095Ssam} 231171095Ssam 232171095Ssam 233171095Ssam/* 234171095Ssam * __hal_device_led_actifity_fix 235171095Ssam * @hldev: pointer to xge_hal_device_t structure 236171095Ssam * 237171095Ssam * SXE-002: Configure link and activity LED to turn it off 238171095Ssam */ 239171095Ssamstatic void 240171095Ssam__hal_device_led_actifity_fix(xge_hal_device_t *hldev) 241171095Ssam{ 242171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 243171095Ssam u16 subid; 244171095Ssam u64 val64; 245171095Ssam 246171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 247173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), &subid); 248171095Ssam 249171095Ssam /* 250171095Ssam * In the case of Herc, there is a new register named beacon control 251171095Ssam * is added which was not present in Xena. 252171095Ssam * Beacon control register in Herc is at the same offset as 253171095Ssam * gpio control register in Xena. It means they are one and same in 254171095Ssam * the case of Xena. Also, gpio control register offset in Herc and 255171095Ssam * Xena is different. 256171095Ssam * The current register map represents Herc(It means we have 257171095Ssam * both beacon and gpio control registers in register map). 258171095Ssam * WRT transition from Xena to Herc, all the code in Xena which was 259171095Ssam * using gpio control register for LED handling would have to 260171095Ssam * use beacon control register in Herc and the rest of the code 261171095Ssam * which uses gpio control in Xena would use the same register 262171095Ssam * in Herc. 263171095Ssam * WRT LED handling(following code), In the case of Herc, beacon 264171095Ssam * control register has to be used. This is applicable for Xena also, 265171095Ssam * since it represents the gpio control register in Xena. 266171095Ssam */ 267171095Ssam if ((subid & 0xFF) >= 0x07) { 268173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 269173139Srwatson &bar0->beacon_control); 270173139Srwatson val64 |= 0x0000800000000000ULL; 271173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 272173139Srwatson val64, &bar0->beacon_control); 273173139Srwatson val64 = 0x0411040400000000ULL; 274173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 275173139Srwatson (void *) ((u8 *)bar0 + 0x2700)); 276171095Ssam } 277171095Ssam} 278171095Ssam 279171095Ssam/* Constants for Fixing the MacAddress problem seen mostly on 280171095Ssam * Alpha machines. 281171095Ssam */ 282171095Ssamstatic u64 xena_fix_mac[] = { 283171095Ssam 0x0060000000000000ULL, 0x0060600000000000ULL, 284171095Ssam 0x0040600000000000ULL, 0x0000600000000000ULL, 285171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 286171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 287171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 288171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 289171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 290171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 291171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 292171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 293171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 294171095Ssam 0x0020600000000000ULL, 0x0060600000000000ULL, 295171095Ssam 0x0020600000000000ULL, 0x0000600000000000ULL, 296171095Ssam 0x0040600000000000ULL, 0x0060600000000000ULL, 297171095Ssam END_SIGN 298171095Ssam}; 299171095Ssam 300171095Ssam/* 301171095Ssam * __hal_device_fix_mac 302171095Ssam * @hldev: HAL device handle. 303171095Ssam * 304171095Ssam * Fix for all "FFs" MAC address problems observed on Alpha platforms. 305171095Ssam */ 306171095Ssamstatic void 307171095Ssam__hal_device_xena_fix_mac(xge_hal_device_t *hldev) 308171095Ssam{ 309171095Ssam int i = 0; 310171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 311171095Ssam 312171095Ssam /* 313171095Ssam * In the case of Herc, there is a new register named beacon control 314171095Ssam * is added which was not present in Xena. 315171095Ssam * Beacon control register in Herc is at the same offset as 316171095Ssam * gpio control register in Xena. It means they are one and same in 317171095Ssam * the case of Xena. Also, gpio control register offset in Herc and 318171095Ssam * Xena is different. 319171095Ssam * The current register map represents Herc(It means we have 320171095Ssam * both beacon and gpio control registers in register map). 321171095Ssam * WRT transition from Xena to Herc, all the code in Xena which was 322171095Ssam * using gpio control register for LED handling would have to 323171095Ssam * use beacon control register in Herc and the rest of the code 324171095Ssam * which uses gpio control in Xena would use the same register 325171095Ssam * in Herc. 326171095Ssam * In the following code(xena_fix_mac), beacon control register has 327171095Ssam * to be used in the case of Xena, since it represents gpio control 328171095Ssam * register. In the case of Herc, there is no change required. 329171095Ssam */ 330171095Ssam while (xena_fix_mac[i] != END_SIGN) { 331173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 332173139Srwatson xena_fix_mac[i++], &bar0->beacon_control); 333173139Srwatson xge_os_mdelay(1); 334171095Ssam } 335171095Ssam} 336171095Ssam 337171095Ssam/* 338171095Ssam * xge_hal_device_bcast_enable 339171095Ssam * @hldev: HAL device handle. 340171095Ssam * 341171095Ssam * Enable receiving broadcasts. 342171095Ssam * The host must first write RMAC_CFG_KEY "key" 343171095Ssam * register, and then - MAC_CFG register. 344171095Ssam */ 345171095Ssamvoid 346171095Ssamxge_hal_device_bcast_enable(xge_hal_device_h devh) 347171095Ssam{ 348171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 349171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 350171095Ssam u64 val64; 351171095Ssam 352171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 353171095Ssam &bar0->mac_cfg); 354173139Srwatson val64 |= XGE_HAL_MAC_RMAC_BCAST_ENABLE; 355171095Ssam 356171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 357173139Srwatson XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); 358171095Ssam 359173139Srwatson __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 360173139Srwatson (u32)(val64 >> 32), &bar0->mac_cfg); 361171095Ssam 362171095Ssam xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s", 363173139Srwatson (unsigned long long)val64, 364173139Srwatson hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled"); 365171095Ssam} 366171095Ssam 367171095Ssam/* 368171095Ssam * xge_hal_device_bcast_disable 369171095Ssam * @hldev: HAL device handle. 370171095Ssam * 371171095Ssam * Disable receiving broadcasts. 372171095Ssam * The host must first write RMAC_CFG_KEY "key" 373171095Ssam * register, and then - MAC_CFG register. 374171095Ssam */ 375171095Ssamvoid 376171095Ssamxge_hal_device_bcast_disable(xge_hal_device_h devh) 377171095Ssam{ 378171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 379171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 380171095Ssam u64 val64; 381171095Ssam 382171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 383171095Ssam &bar0->mac_cfg); 384171095Ssam 385171095Ssam val64 &= ~(XGE_HAL_MAC_RMAC_BCAST_ENABLE); 386171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 387173139Srwatson XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); 388171095Ssam 389173139Srwatson __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 390173139Srwatson (u32)(val64 >> 32), &bar0->mac_cfg); 391171095Ssam 392171095Ssam xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s", 393173139Srwatson (unsigned long long)val64, 394173139Srwatson hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled"); 395171095Ssam} 396171095Ssam 397171095Ssam/* 398171095Ssam * __hal_device_shared_splits_configure 399171095Ssam * @hldev: HAL device handle. 400171095Ssam * 401171095Ssam * TxDMA will stop Read request if the number of read split had exceeded 402171095Ssam * the limit set by shared_splits 403171095Ssam */ 404171095Ssamstatic void 405171095Ssam__hal_device_shared_splits_configure(xge_hal_device_t *hldev) 406171095Ssam{ 407171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 408171095Ssam u64 val64; 409171095Ssam 410171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 411171095Ssam &bar0->pic_control); 412171095Ssam val64 |= 413171095Ssam XGE_HAL_PIC_CNTL_SHARED_SPLITS(hldev->config.shared_splits); 414171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 415173139Srwatson &bar0->pic_control); 416171095Ssam xge_debug_device(XGE_TRACE, "%s", "shared splits configured"); 417171095Ssam} 418171095Ssam 419171095Ssam/* 420171095Ssam * __hal_device_rmac_padding_configure 421171095Ssam * @hldev: HAL device handle. 422171095Ssam * 423171095Ssam * Configure RMAC frame padding. Depends on configuration, it 424171095Ssam * can be send to host or removed by MAC. 425171095Ssam */ 426171095Ssamstatic void 427171095Ssam__hal_device_rmac_padding_configure(xge_hal_device_t *hldev) 428171095Ssam{ 429171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 430171095Ssam u64 val64; 431171095Ssam 432171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 433173139Srwatson XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); 434171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 435171095Ssam &bar0->mac_cfg); 436171095Ssam val64 &= ( ~XGE_HAL_MAC_RMAC_ALL_ADDR_ENABLE ); 437171095Ssam val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE ); 438171095Ssam val64 |= XGE_HAL_MAC_CFG_TMAC_APPEND_PAD; 439171095Ssam 440171095Ssam /* 441171095Ssam * If the RTH enable bit is not set, strip the FCS 442171095Ssam */ 443171095Ssam if (!hldev->config.rth_en || 444171095Ssam !(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 445173139Srwatson &bar0->rts_rth_cfg) & XGE_HAL_RTS_RTH_EN)) { 446173139Srwatson val64 |= XGE_HAL_MAC_CFG_RMAC_STRIP_FCS; 447171095Ssam } 448171095Ssam 449171095Ssam val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_STRIP_PAD ); 450171095Ssam val64 |= XGE_HAL_MAC_RMAC_DISCARD_PFRM; 451171095Ssam 452171095Ssam __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 453173139Srwatson (u32)(val64 >> 32), (char*)&bar0->mac_cfg); 454171095Ssam xge_os_mdelay(1); 455171095Ssam 456171095Ssam xge_debug_device(XGE_TRACE, 457173139Srwatson "mac_cfg 0x"XGE_OS_LLXFMT": frame padding configured", 458173139Srwatson (unsigned long long)val64); 459171095Ssam} 460171095Ssam 461171095Ssam/* 462171095Ssam * __hal_device_pause_frames_configure 463171095Ssam * @hldev: HAL device handle. 464171095Ssam * 465171095Ssam * Set Pause threshold. 466171095Ssam * 467171095Ssam * Pause frame is generated if the amount of data outstanding 468171095Ssam * on any queue exceeded the ratio of 469171095Ssam * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256 470171095Ssam */ 471171095Ssamstatic void 472171095Ssam__hal_device_pause_frames_configure(xge_hal_device_t *hldev) 473171095Ssam{ 474171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 475171095Ssam int i; 476171095Ssam u64 val64; 477171095Ssam 478171095Ssam switch (hldev->config.mac.media) { 479173139Srwatson case XGE_HAL_MEDIA_SR: 480173139Srwatson case XGE_HAL_MEDIA_SW: 481173139Srwatson val64=0xfffbfffbfffbfffbULL; 482173139Srwatson break; 483173139Srwatson case XGE_HAL_MEDIA_LR: 484173139Srwatson case XGE_HAL_MEDIA_LW: 485173139Srwatson val64=0xffbbffbbffbbffbbULL; 486173139Srwatson break; 487173139Srwatson case XGE_HAL_MEDIA_ER: 488173139Srwatson case XGE_HAL_MEDIA_EW: 489173139Srwatson default: 490173139Srwatson val64=0xffbbffbbffbbffbbULL; 491173139Srwatson break; 492171095Ssam } 493171095Ssam 494171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 495173139Srwatson val64, &bar0->mc_pause_thresh_q0q3); 496171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 497173139Srwatson val64, &bar0->mc_pause_thresh_q4q7); 498171095Ssam 499171095Ssam /* Set the time value to be inserted in the pause frame generated 500171095Ssam * by Xframe */ 501171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 502171095Ssam &bar0->rmac_pause_cfg); 503171095Ssam if (hldev->config.mac.rmac_pause_gen_en) 504173139Srwatson val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN; 505171095Ssam else 506173139Srwatson val64 &= ~(XGE_HAL_RMAC_PAUSE_GEN_EN); 507171095Ssam if (hldev->config.mac.rmac_pause_rcv_en) 508173139Srwatson val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN; 509171095Ssam else 510173139Srwatson val64 &= ~(XGE_HAL_RMAC_PAUSE_RCV_EN); 511171095Ssam val64 &= ~(XGE_HAL_RMAC_PAUSE_HG_PTIME(0xffff)); 512171095Ssam val64 |= XGE_HAL_RMAC_PAUSE_HG_PTIME(hldev->config.mac.rmac_pause_time); 513171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 514173139Srwatson &bar0->rmac_pause_cfg); 515171095Ssam 516171095Ssam val64 = 0; 517171095Ssam for (i = 0; i<4; i++) { 518173139Srwatson val64 |= 519173139Srwatson (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q0q3) 520173139Srwatson <<(i*2*8)); 521171095Ssam } 522171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 523173139Srwatson &bar0->mc_pause_thresh_q0q3); 524171095Ssam 525171095Ssam val64 = 0; 526171095Ssam for (i = 0; i<4; i++) { 527173139Srwatson val64 |= 528173139Srwatson (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q4q7) 529173139Srwatson <<(i*2*8)); 530171095Ssam } 531171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 532173139Srwatson &bar0->mc_pause_thresh_q4q7); 533171095Ssam xge_debug_device(XGE_TRACE, "%s", "pause frames configured"); 534171095Ssam} 535171095Ssam 536171095Ssam/* 537171095Ssam * Herc's clock rate doubled, unless the slot is 33MHz. 538171095Ssam */ 539171095Ssamunsigned int __hal_fix_time_ival_herc(xge_hal_device_t *hldev, 540173139Srwatson unsigned int time_ival) 541171095Ssam{ 542171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 543173139Srwatson return time_ival; 544171095Ssam 545171095Ssam xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC); 546171095Ssam 547171095Ssam if (hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN && 548171095Ssam hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_33MHZ) 549173139Srwatson time_ival *= 2; 550171095Ssam 551171095Ssam return time_ival; 552171095Ssam} 553171095Ssam 554171095Ssam 555171095Ssam/* 556171095Ssam * __hal_device_bus_master_disable 557171095Ssam * @hldev: HAL device handle. 558171095Ssam * 559171095Ssam * Disable bus mastership. 560171095Ssam */ 561171095Ssamstatic void 562171095Ssam__hal_device_bus_master_disable (xge_hal_device_t *hldev) 563171095Ssam{ 564171095Ssam u16 cmd; 565171095Ssam u16 bus_master = 4; 566171095Ssam 567171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 568173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); 569171095Ssam cmd &= ~bus_master; 570171095Ssam xge_os_pci_write16(hldev->pdev, hldev->cfgh, 571173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, command), cmd); 572171095Ssam} 573171095Ssam 574171095Ssam/* 575171095Ssam * __hal_device_bus_master_enable 576171095Ssam * @hldev: HAL device handle. 577171095Ssam * 578171095Ssam * Disable bus mastership. 579171095Ssam */ 580171095Ssamstatic void 581171095Ssam__hal_device_bus_master_enable (xge_hal_device_t *hldev) 582171095Ssam{ 583171095Ssam u16 cmd; 584171095Ssam u16 bus_master = 4; 585171095Ssam 586171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 587173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); 588171095Ssam 589171095Ssam /* already enabled? do nothing */ 590171095Ssam if (cmd & bus_master) 591173139Srwatson return; 592171095Ssam 593171095Ssam cmd |= bus_master; 594171095Ssam xge_os_pci_write16(hldev->pdev, hldev->cfgh, 595173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, command), cmd); 596171095Ssam} 597171095Ssam/* 598171095Ssam * __hal_device_intr_mgmt 599171095Ssam * @hldev: HAL device handle. 600171095Ssam * @mask: mask indicating which Intr block must be modified. 601171095Ssam * @flag: if true - enable, otherwise - disable interrupts. 602171095Ssam * 603171095Ssam * Disable or enable device interrupts. Mask is used to specify 604171095Ssam * which hardware blocks should produce interrupts. For details 605171095Ssam * please refer to Xframe User Guide. 606171095Ssam */ 607171095Ssamstatic void 608171095Ssam__hal_device_intr_mgmt(xge_hal_device_t *hldev, u64 mask, int flag) 609171095Ssam{ 610171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 611171095Ssam u64 val64 = 0, temp64 = 0; 612171095Ssam u64 gim, gim_saved; 613171095Ssam 614171095Ssam gim_saved = gim = xge_os_pio_mem_read64(hldev->pdev, 615173139Srwatson hldev->regh0, &bar0->general_int_mask); 616171095Ssam 617171095Ssam /* Top level interrupt classification */ 618171095Ssam /* PIC Interrupts */ 619171095Ssam if ((mask & (XGE_HAL_TX_PIC_INTR/* | XGE_HAL_RX_PIC_INTR*/))) { 620173139Srwatson /* Enable PIC Intrs in the general intr mask register */ 621173139Srwatson val64 = XGE_HAL_TXPIC_INT_M/* | XGE_HAL_PIC_RX_INT_M*/; 622173139Srwatson if (flag) { 623173139Srwatson gim &= ~((u64) val64); 624173139Srwatson temp64 = xge_os_pio_mem_read64(hldev->pdev, 625173139Srwatson hldev->regh0, &bar0->pic_int_mask); 626171095Ssam 627173139Srwatson temp64 &= ~XGE_HAL_PIC_INT_TX; 628171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 629173139Srwatson if (xge_hal_device_check_id(hldev) == 630173139Srwatson XGE_HAL_CARD_HERC) { 631173139Srwatson temp64 &= ~XGE_HAL_PIC_INT_MISC; 632173139Srwatson } 633171095Ssam#endif 634173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 635173139Srwatson temp64, &bar0->pic_int_mask); 636171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 637173139Srwatson if (xge_hal_device_check_id(hldev) == 638173139Srwatson XGE_HAL_CARD_HERC) { 639173139Srwatson /* 640173139Srwatson * Unmask only Link Up interrupt 641173139Srwatson */ 642173139Srwatson temp64 = xge_os_pio_mem_read64(hldev->pdev, 643173139Srwatson hldev->regh0, &bar0->misc_int_mask); 644173139Srwatson temp64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; 645173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 646173139Srwatson hldev->regh0, temp64, 647173139Srwatson &bar0->misc_int_mask); 648173139Srwatson xge_debug_device(XGE_TRACE, 649173139Srwatson "unmask link up flag "XGE_OS_LLXFMT, 650173139Srwatson (unsigned long long)temp64); 651173139Srwatson } 652171095Ssam#endif 653173139Srwatson } else { /* flag == 0 */ 654171095Ssam 655171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 656173139Srwatson if (xge_hal_device_check_id(hldev) == 657173139Srwatson XGE_HAL_CARD_HERC) { 658173139Srwatson /* 659173139Srwatson * Mask both Link Up and Down interrupts 660173139Srwatson */ 661173139Srwatson temp64 = xge_os_pio_mem_read64(hldev->pdev, 662173139Srwatson hldev->regh0, &bar0->misc_int_mask); 663173139Srwatson temp64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; 664173139Srwatson temp64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 665173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 666173139Srwatson hldev->regh0, temp64, 667173139Srwatson &bar0->misc_int_mask); 668173139Srwatson xge_debug_device(XGE_TRACE, 669173139Srwatson "mask link up/down flag "XGE_OS_LLXFMT, 670173139Srwatson (unsigned long long)temp64); 671173139Srwatson } 672171095Ssam#endif 673173139Srwatson /* Disable PIC Intrs in the general intr mask 674173139Srwatson * register */ 675173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 676173139Srwatson XGE_HAL_ALL_INTRS_DIS, 677173139Srwatson &bar0->pic_int_mask); 678173139Srwatson gim |= val64; 679173139Srwatson } 680171095Ssam } 681171095Ssam 682171095Ssam /* DMA Interrupts */ 683171095Ssam /* Enabling/Disabling Tx DMA interrupts */ 684171095Ssam if (mask & XGE_HAL_TX_DMA_INTR) { 685173139Srwatson /* Enable TxDMA Intrs in the general intr mask register */ 686173139Srwatson val64 = XGE_HAL_TXDMA_INT_M; 687173139Srwatson if (flag) { 688173139Srwatson gim &= ~((u64) val64); 689173139Srwatson /* Enable all TxDMA interrupts */ 690173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 691173139Srwatson 0x0, &bar0->txdma_int_mask); 692173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 693173139Srwatson 0x0, &bar0->pfc_err_mask); 694173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 695173139Srwatson 0x0, &bar0->tda_err_mask); 696173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 697173139Srwatson 0x0, &bar0->pcc_err_mask); 698173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 699173139Srwatson 0x0, &bar0->tti_err_mask); 700173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 701173139Srwatson 0x0, &bar0->lso_err_mask); 702173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 703173139Srwatson 0x0, &bar0->tpa_err_mask); 704173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 705173139Srwatson 0x0, &bar0->sm_err_mask); 706171095Ssam 707173139Srwatson } else { /* flag == 0 */ 708171095Ssam 709173139Srwatson /* Disable TxDMA Intrs in the general intr mask 710173139Srwatson * register */ 711173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 712173139Srwatson XGE_HAL_ALL_INTRS_DIS, 713173139Srwatson &bar0->txdma_int_mask); 714173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 715173139Srwatson XGE_HAL_ALL_INTRS_DIS, 716173139Srwatson &bar0->pfc_err_mask); 717171095Ssam 718173139Srwatson gim |= val64; 719173139Srwatson } 720171095Ssam } 721171095Ssam 722171095Ssam /* Enabling/Disabling Rx DMA interrupts */ 723171095Ssam if (mask & XGE_HAL_RX_DMA_INTR) { 724173139Srwatson /* Enable RxDMA Intrs in the general intr mask register */ 725173139Srwatson val64 = XGE_HAL_RXDMA_INT_M; 726173139Srwatson if (flag) { 727171095Ssam 728173139Srwatson gim &= ~((u64) val64); 729173139Srwatson /* All RxDMA block interrupts are disabled for now 730173139Srwatson * TODO */ 731173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 732173139Srwatson XGE_HAL_ALL_INTRS_DIS, 733173139Srwatson &bar0->rxdma_int_mask); 734171095Ssam 735173139Srwatson } else { /* flag == 0 */ 736171095Ssam 737173139Srwatson /* Disable RxDMA Intrs in the general intr mask 738173139Srwatson * register */ 739173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 740173139Srwatson XGE_HAL_ALL_INTRS_DIS, 741173139Srwatson &bar0->rxdma_int_mask); 742171095Ssam 743173139Srwatson gim |= val64; 744173139Srwatson } 745171095Ssam } 746171095Ssam 747171095Ssam /* MAC Interrupts */ 748171095Ssam /* Enabling/Disabling MAC interrupts */ 749171095Ssam if (mask & (XGE_HAL_TX_MAC_INTR | XGE_HAL_RX_MAC_INTR)) { 750173139Srwatson val64 = XGE_HAL_TXMAC_INT_M | XGE_HAL_RXMAC_INT_M; 751173139Srwatson if (flag) { 752171095Ssam 753173139Srwatson gim &= ~((u64) val64); 754171095Ssam 755173139Srwatson /* All MAC block error inter. are disabled for now. */ 756173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 757173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask); 758173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 759173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask); 760171095Ssam 761173139Srwatson } else { /* flag == 0 */ 762171095Ssam 763173139Srwatson /* Disable MAC Intrs in the general intr mask 764173139Srwatson * register */ 765173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 766173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask); 767173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 768173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask); 769171095Ssam 770173139Srwatson gim |= val64; 771173139Srwatson } 772171095Ssam } 773171095Ssam 774171095Ssam /* XGXS Interrupts */ 775171095Ssam if (mask & (XGE_HAL_TX_XGXS_INTR | XGE_HAL_RX_XGXS_INTR)) { 776173139Srwatson val64 = XGE_HAL_TXXGXS_INT_M | XGE_HAL_RXXGXS_INT_M; 777173139Srwatson if (flag) { 778171095Ssam 779173139Srwatson gim &= ~((u64) val64); 780173139Srwatson /* All XGXS block error interrupts are disabled for now 781173139Srwatson * TODO */ 782173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 783173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask); 784171095Ssam 785173139Srwatson } else { /* flag == 0 */ 786171095Ssam 787173139Srwatson /* Disable MC Intrs in the general intr mask register */ 788173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 789173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask); 790171095Ssam 791173139Srwatson gim |= val64; 792173139Srwatson } 793171095Ssam } 794171095Ssam 795171095Ssam /* Memory Controller(MC) interrupts */ 796171095Ssam if (mask & XGE_HAL_MC_INTR) { 797173139Srwatson val64 = XGE_HAL_MC_INT_M; 798173139Srwatson if (flag) { 799171095Ssam 800173139Srwatson gim &= ~((u64) val64); 801171095Ssam 802173139Srwatson /* Enable all MC blocks error interrupts */ 803173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 804173139Srwatson 0x0ULL, &bar0->mc_int_mask); 805171095Ssam 806173139Srwatson } else { /* flag == 0 */ 807171095Ssam 808173139Srwatson /* Disable MC Intrs in the general intr mask 809173139Srwatson * register */ 810173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 811173139Srwatson XGE_HAL_ALL_INTRS_DIS, &bar0->mc_int_mask); 812171095Ssam 813173139Srwatson gim |= val64; 814173139Srwatson } 815171095Ssam } 816171095Ssam 817171095Ssam 818171095Ssam /* Tx traffic interrupts */ 819171095Ssam if (mask & XGE_HAL_TX_TRAFFIC_INTR) { 820173139Srwatson val64 = XGE_HAL_TXTRAFFIC_INT_M; 821173139Srwatson if (flag) { 822171095Ssam 823173139Srwatson gim &= ~((u64) val64); 824171095Ssam 825173139Srwatson /* Enable all the Tx side interrupts */ 826173139Srwatson /* '0' Enables all 64 TX interrupt levels. */ 827173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0, 828173139Srwatson &bar0->tx_traffic_mask); 829171095Ssam 830173139Srwatson } else { /* flag == 0 */ 831171095Ssam 832173139Srwatson /* Disable Tx Traffic Intrs in the general intr mask 833173139Srwatson * register. */ 834173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 835173139Srwatson XGE_HAL_ALL_INTRS_DIS, 836173139Srwatson &bar0->tx_traffic_mask); 837173139Srwatson gim |= val64; 838173139Srwatson } 839171095Ssam } 840171095Ssam 841171095Ssam /* Rx traffic interrupts */ 842171095Ssam if (mask & XGE_HAL_RX_TRAFFIC_INTR) { 843173139Srwatson val64 = XGE_HAL_RXTRAFFIC_INT_M; 844173139Srwatson if (flag) { 845173139Srwatson gim &= ~((u64) val64); 846173139Srwatson /* '0' Enables all 8 RX interrupt levels. */ 847173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0, 848173139Srwatson &bar0->rx_traffic_mask); 849171095Ssam 850173139Srwatson } else { /* flag == 0 */ 851171095Ssam 852173139Srwatson /* Disable Rx Traffic Intrs in the general intr mask 853173139Srwatson * register. 854173139Srwatson */ 855173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 856173139Srwatson XGE_HAL_ALL_INTRS_DIS, 857173139Srwatson &bar0->rx_traffic_mask); 858171095Ssam 859173139Srwatson gim |= val64; 860173139Srwatson } 861171095Ssam } 862171095Ssam 863171095Ssam /* Sched Timer interrupt */ 864171095Ssam if (mask & XGE_HAL_SCHED_INTR) { 865173139Srwatson if (flag) { 866173139Srwatson temp64 = xge_os_pio_mem_read64(hldev->pdev, 867173139Srwatson hldev->regh0, &bar0->txpic_int_mask); 868173139Srwatson temp64 &= ~XGE_HAL_TXPIC_INT_SCHED_INTR; 869173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 870173139Srwatson temp64, &bar0->txpic_int_mask); 871171095Ssam 872173139Srwatson xge_hal_device_sched_timer(hldev, 873173139Srwatson hldev->config.sched_timer_us, 874173139Srwatson hldev->config.sched_timer_one_shot); 875173139Srwatson } else { 876173139Srwatson temp64 = xge_os_pio_mem_read64(hldev->pdev, 877173139Srwatson hldev->regh0, &bar0->txpic_int_mask); 878173139Srwatson temp64 |= XGE_HAL_TXPIC_INT_SCHED_INTR; 879171095Ssam 880173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 881173139Srwatson temp64, &bar0->txpic_int_mask); 882171095Ssam 883173139Srwatson xge_hal_device_sched_timer(hldev, 884173139Srwatson XGE_HAL_SCHED_TIMER_DISABLED, 885173139Srwatson XGE_HAL_SCHED_TIMER_ON_SHOT_ENABLE); 886173139Srwatson } 887171095Ssam } 888171095Ssam 889171095Ssam if (gim != gim_saved) { 890173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, gim, 891173139Srwatson &bar0->general_int_mask); 892173139Srwatson xge_debug_device(XGE_TRACE, "general_int_mask updated " 893173139Srwatson XGE_OS_LLXFMT" => "XGE_OS_LLXFMT, 894173139Srwatson (unsigned long long)gim_saved, (unsigned long long)gim); 895171095Ssam } 896171095Ssam} 897171095Ssam 898171095Ssam/* 899171095Ssam * __hal_device_bimodal_configure 900171095Ssam * @hldev: HAL device handle. 901171095Ssam * 902171095Ssam * Bimodal parameters initialization. 903171095Ssam */ 904171095Ssamstatic void 905171095Ssam__hal_device_bimodal_configure(xge_hal_device_t *hldev) 906171095Ssam{ 907171095Ssam int i; 908171095Ssam 909171095Ssam for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { 910173139Srwatson xge_hal_tti_config_t *tti; 911173139Srwatson xge_hal_rti_config_t *rti; 912171095Ssam 913173139Srwatson if (!hldev->config.ring.queue[i].configured) 914173139Srwatson continue; 915173139Srwatson rti = &hldev->config.ring.queue[i].rti; 916173139Srwatson tti = &hldev->bimodal_tti[i]; 917171095Ssam 918173139Srwatson tti->enabled = 1; 919173139Srwatson tti->urange_a = hldev->bimodal_urange_a_en * 10; 920173139Srwatson tti->urange_b = 20; 921173139Srwatson tti->urange_c = 30; 922173139Srwatson tti->ufc_a = hldev->bimodal_urange_a_en * 8; 923173139Srwatson tti->ufc_b = 16; 924173139Srwatson tti->ufc_c = 32; 925173139Srwatson tti->ufc_d = 64; 926173139Srwatson tti->timer_val_us = hldev->bimodal_timer_val_us; 927173139Srwatson tti->timer_ac_en = 1; 928173139Srwatson tti->timer_ci_en = 0; 929171095Ssam 930173139Srwatson rti->urange_a = 10; 931173139Srwatson rti->urange_b = 20; 932173139Srwatson rti->urange_c = 30; 933173139Srwatson rti->ufc_a = 1; /* <= for netpipe type of tests */ 934173139Srwatson rti->ufc_b = 4; 935173139Srwatson rti->ufc_c = 4; 936173139Srwatson rti->ufc_d = 4; /* <= 99% of a bandwidth traffic counts here */ 937173139Srwatson rti->timer_ac_en = 1; 938173139Srwatson rti->timer_val_us = 5; /* for optimal bus efficiency usage */ 939171095Ssam } 940171095Ssam} 941171095Ssam 942171095Ssam/* 943171095Ssam * __hal_device_tti_apply 944171095Ssam * @hldev: HAL device handle. 945171095Ssam * 946171095Ssam * apply TTI configuration. 947171095Ssam */ 948171095Ssamstatic xge_hal_status_e 949171095Ssam__hal_device_tti_apply(xge_hal_device_t *hldev, xge_hal_tti_config_t *tti, 950173139Srwatson int num, int runtime) 951171095Ssam{ 952171095Ssam u64 val64, data1 = 0, data2 = 0; 953171095Ssam xge_hal_pci_bar0_t *bar0; 954171095Ssam 955171095Ssam if (runtime) 956173139Srwatson bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 957171095Ssam else 958173139Srwatson bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 959171095Ssam 960171095Ssam if (tti->timer_val_us) { 961173139Srwatson unsigned int tx_interval; 962171095Ssam 963173139Srwatson if (hldev->config.pci_freq_mherz) { 964173139Srwatson tx_interval = hldev->config.pci_freq_mherz * 965173139Srwatson tti->timer_val_us / 64; 966173139Srwatson tx_interval = 967173139Srwatson __hal_fix_time_ival_herc(hldev, 968173139Srwatson tx_interval); 969173139Srwatson } else { 970173139Srwatson tx_interval = tti->timer_val_us; 971173139Srwatson } 972173139Srwatson data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_VAL(tx_interval); 973173139Srwatson if (tti->timer_ac_en) { 974173139Srwatson data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_AC_EN; 975173139Srwatson } 976173139Srwatson if (tti->timer_ci_en) { 977173139Srwatson data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_CI_EN; 978173139Srwatson } 979171095Ssam 980173139Srwatson if (!runtime) { 981173139Srwatson xge_debug_device(XGE_TRACE, "TTI[%d] timer enabled to %d, ci %s", 982173139Srwatson num, tx_interval, tti->timer_ci_en ? 983173139Srwatson "enabled": "disabled"); 984173139Srwatson } 985171095Ssam } 986171095Ssam 987171095Ssam if (tti->urange_a || 988171095Ssam tti->urange_b || 989171095Ssam tti->urange_c || 990171095Ssam tti->ufc_a || 991171095Ssam tti->ufc_b || 992171095Ssam tti->ufc_c || 993171095Ssam tti->ufc_d ) { 994173139Srwatson data1 |= XGE_HAL_TTI_DATA1_MEM_TX_URNG_A(tti->urange_a) | 995173139Srwatson XGE_HAL_TTI_DATA1_MEM_TX_URNG_B(tti->urange_b) | 996173139Srwatson XGE_HAL_TTI_DATA1_MEM_TX_URNG_C(tti->urange_c); 997171095Ssam 998173139Srwatson data2 |= XGE_HAL_TTI_DATA2_MEM_TX_UFC_A(tti->ufc_a) | 999173139Srwatson XGE_HAL_TTI_DATA2_MEM_TX_UFC_B(tti->ufc_b) | 1000173139Srwatson XGE_HAL_TTI_DATA2_MEM_TX_UFC_C(tti->ufc_c) | 1001173139Srwatson XGE_HAL_TTI_DATA2_MEM_TX_UFC_D(tti->ufc_d); 1002171095Ssam } 1003171095Ssam 1004171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data1, 1005173139Srwatson &bar0->tti_data1_mem); 1006171095Ssam (void)xge_os_pio_mem_read64(hldev->pdev, 1007173139Srwatson hldev->regh0, &bar0->tti_data1_mem); 1008171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data2, 1009173139Srwatson &bar0->tti_data2_mem); 1010171095Ssam (void)xge_os_pio_mem_read64(hldev->pdev, 1011173139Srwatson hldev->regh0, &bar0->tti_data2_mem); 1012171095Ssam xge_os_wmb(); 1013171095Ssam 1014171095Ssam val64 = XGE_HAL_TTI_CMD_MEM_WE | XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD | 1015171095Ssam XGE_HAL_TTI_CMD_MEM_OFFSET(num); 1016171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1017173139Srwatson &bar0->tti_command_mem); 1018171095Ssam 1019171095Ssam if (!runtime && __hal_device_register_poll(hldev, &bar0->tti_command_mem, 1020173139Srwatson 0, XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD, 1021173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1022173139Srwatson /* upper layer may require to repeat */ 1023173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1024171095Ssam } 1025171095Ssam 1026171095Ssam if (!runtime) { 1027173139Srwatson xge_debug_device(XGE_TRACE, "TTI[%d] configured: tti_data1_mem 0x" 1028173139Srwatson XGE_OS_LLXFMT, num, 1029173139Srwatson (unsigned long long)xge_os_pio_mem_read64(hldev->pdev, 1030173139Srwatson hldev->regh0, &bar0->tti_data1_mem)); 1031171095Ssam } 1032171095Ssam 1033171095Ssam return XGE_HAL_OK; 1034171095Ssam} 1035171095Ssam 1036171095Ssam/* 1037171095Ssam * __hal_device_tti_configure 1038171095Ssam * @hldev: HAL device handle. 1039171095Ssam * 1040171095Ssam * TTI Initialization. 1041171095Ssam * Initialize Transmit Traffic Interrupt Scheme. 1042171095Ssam */ 1043171095Ssamstatic xge_hal_status_e 1044171095Ssam__hal_device_tti_configure(xge_hal_device_t *hldev, int runtime) 1045171095Ssam{ 1046171095Ssam int i; 1047171095Ssam 1048171095Ssam for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) { 1049173139Srwatson int j; 1050171095Ssam 1051173139Srwatson if (!hldev->config.fifo.queue[i].configured) 1052173139Srwatson continue; 1053171095Ssam 1054173139Srwatson for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) { 1055173139Srwatson xge_hal_status_e status; 1056171095Ssam 1057173139Srwatson if (!hldev->config.fifo.queue[i].tti[j].enabled) 1058173139Srwatson continue; 1059171095Ssam 1060173139Srwatson /* at least some TTI enabled. Record it. */ 1061173139Srwatson hldev->tti_enabled = 1; 1062171095Ssam 1063173139Srwatson status = __hal_device_tti_apply(hldev, 1064173139Srwatson &hldev->config.fifo.queue[i].tti[j], 1065173139Srwatson i * XGE_HAL_MAX_FIFO_TTI_NUM + j, runtime); 1066173139Srwatson if (status != XGE_HAL_OK) 1067173139Srwatson return status; 1068173139Srwatson } 1069171095Ssam } 1070171095Ssam 1071171095Ssam /* processing bimodal TTIs */ 1072171095Ssam for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { 1073173139Srwatson xge_hal_status_e status; 1074171095Ssam 1075173139Srwatson if (!hldev->bimodal_tti[i].enabled) 1076173139Srwatson continue; 1077171095Ssam 1078173139Srwatson /* at least some bimodal TTI enabled. Record it. */ 1079173139Srwatson hldev->tti_enabled = 1; 1080171095Ssam 1081173139Srwatson status = __hal_device_tti_apply(hldev, &hldev->bimodal_tti[i], 1082173139Srwatson XGE_HAL_MAX_FIFO_TTI_RING_0 + i, runtime); 1083173139Srwatson if (status != XGE_HAL_OK) 1084173139Srwatson return status; 1085171095Ssam 1086171095Ssam } 1087171095Ssam 1088171095Ssam return XGE_HAL_OK; 1089171095Ssam} 1090171095Ssam 1091171095Ssam/* 1092171095Ssam * __hal_device_rti_configure 1093171095Ssam * @hldev: HAL device handle. 1094171095Ssam * 1095171095Ssam * RTI Initialization. 1096171095Ssam * Initialize Receive Traffic Interrupt Scheme. 1097171095Ssam */ 1098171095Ssamxge_hal_status_e 1099171095Ssam__hal_device_rti_configure(xge_hal_device_t *hldev, int runtime) 1100171095Ssam{ 1101171095Ssam xge_hal_pci_bar0_t *bar0; 1102171095Ssam u64 val64, data1 = 0, data2 = 0; 1103171095Ssam int i; 1104171095Ssam 1105171095Ssam if (runtime) { 1106173139Srwatson /* 1107173139Srwatson * we don't want to re-configure RTI in case when 1108173139Srwatson * bimodal interrupts are in use. Instead reconfigure TTI 1109173139Srwatson * with new RTI values. 1110173139Srwatson */ 1111173139Srwatson if (hldev->config.bimodal_interrupts) { 1112173139Srwatson __hal_device_bimodal_configure(hldev); 1113173139Srwatson return __hal_device_tti_configure(hldev, 1); 1114173139Srwatson } 1115173139Srwatson bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 1116171095Ssam } else 1117173139Srwatson bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1118171095Ssam 1119171095Ssam for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { 1120173139Srwatson xge_hal_rti_config_t *rti = &hldev->config.ring.queue[i].rti; 1121171095Ssam 1122173139Srwatson if (!hldev->config.ring.queue[i].configured) 1123173139Srwatson continue; 1124171095Ssam 1125173139Srwatson if (rti->timer_val_us) { 1126173139Srwatson unsigned int rx_interval; 1127171095Ssam 1128173139Srwatson if (hldev->config.pci_freq_mherz) { 1129173139Srwatson rx_interval = hldev->config.pci_freq_mherz * 1130173139Srwatson rti->timer_val_us / 8; 1131173139Srwatson rx_interval = 1132173139Srwatson __hal_fix_time_ival_herc(hldev, 1133173139Srwatson rx_interval); 1134173139Srwatson } else { 1135173139Srwatson rx_interval = rti->timer_val_us; 1136173139Srwatson } 1137173139Srwatson data1 |=XGE_HAL_RTI_DATA1_MEM_RX_TIMER_VAL(rx_interval); 1138173139Srwatson if (rti->timer_ac_en) { 1139173139Srwatson data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_AC_EN; 1140173139Srwatson } 1141173139Srwatson data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_CI_EN; 1142173139Srwatson } 1143171095Ssam 1144173139Srwatson if (rti->urange_a || 1145173139Srwatson rti->urange_b || 1146173139Srwatson rti->urange_c || 1147173139Srwatson rti->ufc_a || 1148173139Srwatson rti->ufc_b || 1149173139Srwatson rti->ufc_c || 1150173139Srwatson rti->ufc_d) { 1151173139Srwatson data1 |=XGE_HAL_RTI_DATA1_MEM_RX_URNG_A(rti->urange_a) | 1152173139Srwatson XGE_HAL_RTI_DATA1_MEM_RX_URNG_B(rti->urange_b) | 1153173139Srwatson XGE_HAL_RTI_DATA1_MEM_RX_URNG_C(rti->urange_c); 1154171095Ssam 1155173139Srwatson data2 |= XGE_HAL_RTI_DATA2_MEM_RX_UFC_A(rti->ufc_a) | 1156173139Srwatson XGE_HAL_RTI_DATA2_MEM_RX_UFC_B(rti->ufc_b) | 1157173139Srwatson XGE_HAL_RTI_DATA2_MEM_RX_UFC_C(rti->ufc_c) | 1158173139Srwatson XGE_HAL_RTI_DATA2_MEM_RX_UFC_D(rti->ufc_d); 1159173139Srwatson } 1160171095Ssam 1161173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data1, 1162173139Srwatson &bar0->rti_data1_mem); 1163173139Srwatson (void)xge_os_pio_mem_read64(hldev->pdev, 1164173139Srwatson hldev->regh0, &bar0->rti_data1_mem); 1165173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, data2, 1166173139Srwatson &bar0->rti_data2_mem); 1167173139Srwatson (void)xge_os_pio_mem_read64(hldev->pdev, 1168173139Srwatson hldev->regh0, &bar0->rti_data2_mem); 1169173139Srwatson xge_os_wmb(); 1170171095Ssam 1171173139Srwatson val64 = XGE_HAL_RTI_CMD_MEM_WE | 1172173139Srwatson XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD; 1173173139Srwatson val64 |= XGE_HAL_RTI_CMD_MEM_OFFSET(i); 1174173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1175173139Srwatson &bar0->rti_command_mem); 1176171095Ssam 1177173139Srwatson if (!runtime && __hal_device_register_poll(hldev, 1178173139Srwatson &bar0->rti_command_mem, 0, 1179173139Srwatson XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD, 1180173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1181173139Srwatson /* upper layer may require to repeat */ 1182173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1183173139Srwatson } 1184171095Ssam 1185173139Srwatson if (!runtime) { 1186173139Srwatson xge_debug_device(XGE_TRACE, 1187173139Srwatson "RTI[%d] configured: rti_data1_mem 0x"XGE_OS_LLXFMT, 1188173139Srwatson i, 1189173139Srwatson (unsigned long long)xge_os_pio_mem_read64(hldev->pdev, 1190173139Srwatson hldev->regh0, &bar0->rti_data1_mem)); 1191173139Srwatson } 1192171095Ssam } 1193171095Ssam 1194171095Ssam return XGE_HAL_OK; 1195171095Ssam} 1196171095Ssam 1197171095Ssam 1198171095Ssam/* Constants to be programmed into the Xena's registers to configure 1199171095Ssam * the XAUI. */ 1200171095Ssamstatic u64 default_xena_mdio_cfg[] = { 1201171095Ssam /* Reset PMA PLL */ 1202171095Ssam 0xC001010000000000ULL, 0xC0010100000000E0ULL, 1203171095Ssam 0xC0010100008000E4ULL, 1204171095Ssam /* Remove Reset from PMA PLL */ 1205171095Ssam 0xC001010000000000ULL, 0xC0010100000000E0ULL, 1206171095Ssam 0xC0010100000000E4ULL, 1207171095Ssam END_SIGN 1208171095Ssam}; 1209171095Ssam 1210171095Ssamstatic u64 default_herc_mdio_cfg[] = { 1211171095Ssam END_SIGN 1212171095Ssam}; 1213171095Ssam 1214171095Ssamstatic u64 default_xena_dtx_cfg[] = { 1215171095Ssam 0x8000051500000000ULL, 0x80000515000000E0ULL, 1216171095Ssam 0x80000515D93500E4ULL, 0x8001051500000000ULL, 1217171095Ssam 0x80010515000000E0ULL, 0x80010515001E00E4ULL, 1218171095Ssam 0x8002051500000000ULL, 0x80020515000000E0ULL, 1219171095Ssam 0x80020515F21000E4ULL, 1220171095Ssam /* Set PADLOOPBACKN */ 1221171095Ssam 0x8002051500000000ULL, 0x80020515000000E0ULL, 1222171095Ssam 0x80020515B20000E4ULL, 0x8003051500000000ULL, 1223171095Ssam 0x80030515000000E0ULL, 0x80030515B20000E4ULL, 1224171095Ssam 0x8004051500000000ULL, 0x80040515000000E0ULL, 1225171095Ssam 0x80040515B20000E4ULL, 0x8005051500000000ULL, 1226171095Ssam 0x80050515000000E0ULL, 0x80050515B20000E4ULL, 1227171095Ssam SWITCH_SIGN, 1228171095Ssam /* Remove PADLOOPBACKN */ 1229171095Ssam 0x8002051500000000ULL, 0x80020515000000E0ULL, 1230171095Ssam 0x80020515F20000E4ULL, 0x8003051500000000ULL, 1231171095Ssam 0x80030515000000E0ULL, 0x80030515F20000E4ULL, 1232171095Ssam 0x8004051500000000ULL, 0x80040515000000E0ULL, 1233171095Ssam 0x80040515F20000E4ULL, 0x8005051500000000ULL, 1234171095Ssam 0x80050515000000E0ULL, 0x80050515F20000E4ULL, 1235171095Ssam END_SIGN 1236171095Ssam}; 1237171095Ssam 1238171095Ssam/* 1239171095Ssamstatic u64 default_herc_dtx_cfg[] = { 1240171095Ssam 0x80000515BA750000ULL, 0x80000515BA7500E0ULL, 1241171095Ssam 0x80000515BA750004ULL, 0x80000515BA7500E4ULL, 1242171095Ssam 0x80010515003F0000ULL, 0x80010515003F00E0ULL, 1243171095Ssam 0x80010515003F0004ULL, 0x80010515003F00E4ULL, 1244171095Ssam 0x80020515F2100000ULL, 0x80020515F21000E0ULL, 1245171095Ssam 0x80020515F2100004ULL, 0x80020515F21000E4ULL, 1246171095Ssam END_SIGN 1247171095Ssam}; 1248171095Ssam*/ 1249171095Ssam 1250171095Ssamstatic u64 default_herc_dtx_cfg[] = { 1251173139Srwatson 0x8000051536750000ULL, 0x80000515367500E0ULL, 1252173139Srwatson 0x8000051536750004ULL, 0x80000515367500E4ULL, 1253171095Ssam 1254173139Srwatson 0x80010515003F0000ULL, 0x80010515003F00E0ULL, 1255173139Srwatson 0x80010515003F0004ULL, 0x80010515003F00E4ULL, 1256171095Ssam 1257173139Srwatson 0x801205150D440000ULL, 0x801205150D4400E0ULL, 1258173139Srwatson 0x801205150D440004ULL, 0x801205150D4400E4ULL, 1259171095Ssam 1260173139Srwatson 0x80020515F2100000ULL, 0x80020515F21000E0ULL, 1261173139Srwatson 0x80020515F2100004ULL, 0x80020515F21000E4ULL, 1262173139Srwatson END_SIGN 1263171095Ssam}; 1264171095Ssam 1265171095Ssam 1266171095Ssamvoid 1267171095Ssam__hal_serial_mem_write64(xge_hal_device_t *hldev, u64 value, u64 *reg) 1268171095Ssam{ 1269171095Ssam __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 1270173139Srwatson (u32)(value>>32), reg); 1271171095Ssam xge_os_wmb(); 1272171095Ssam __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, 1273173139Srwatson (u32)value, reg); 1274171095Ssam xge_os_wmb(); 1275171095Ssam xge_os_mdelay(1); 1276171095Ssam} 1277171095Ssam 1278171095Ssamu64 1279171095Ssam__hal_serial_mem_read64(xge_hal_device_t *hldev, u64 *reg) 1280171095Ssam{ 1281171095Ssam u64 val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1282173139Srwatson reg); 1283171095Ssam xge_os_mdelay(1); 1284171095Ssam return val64; 1285171095Ssam} 1286171095Ssam 1287171095Ssam/* 1288171095Ssam * __hal_device_xaui_configure 1289171095Ssam * @hldev: HAL device handle. 1290171095Ssam * 1291171095Ssam * Configure XAUI Interface of Xena. 1292171095Ssam * 1293171095Ssam * To Configure the Xena's XAUI, one has to write a series 1294171095Ssam * of 64 bit values into two registers in a particular 1295171095Ssam * sequence. Hence a macro 'SWITCH_SIGN' has been defined 1296171095Ssam * which will be defined in the array of configuration values 1297171095Ssam * (default_dtx_cfg & default_mdio_cfg) at appropriate places 1298171095Ssam * to switch writing from one regsiter to another. We continue 1299171095Ssam * writing these values until we encounter the 'END_SIGN' macro. 1300171095Ssam * For example, After making a series of 21 writes into 1301171095Ssam * dtx_control register the 'SWITCH_SIGN' appears and hence we 1302171095Ssam * start writing into mdio_control until we encounter END_SIGN. 1303171095Ssam */ 1304171095Ssamstatic void 1305171095Ssam__hal_device_xaui_configure(xge_hal_device_t *hldev) 1306171095Ssam{ 1307171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1308171095Ssam int mdio_cnt = 0, dtx_cnt = 0; 1309171095Ssam u64 *default_dtx_cfg = NULL, *default_mdio_cfg = NULL; 1310171095Ssam 1311171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 1312173139Srwatson default_dtx_cfg = default_xena_dtx_cfg; 1313173139Srwatson default_mdio_cfg = default_xena_mdio_cfg; 1314171095Ssam } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 1315173139Srwatson default_dtx_cfg = default_herc_dtx_cfg; 1316173139Srwatson default_mdio_cfg = default_herc_mdio_cfg; 1317171095Ssam } else { 1318173139Srwatson xge_assert(default_dtx_cfg); 1319173139Srwatson return; 1320171095Ssam } 1321171095Ssam 1322171095Ssam do { 1323171095Ssam dtx_cfg: 1324173139Srwatson while (default_dtx_cfg[dtx_cnt] != END_SIGN) { 1325173139Srwatson if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { 1326173139Srwatson dtx_cnt++; 1327173139Srwatson goto mdio_cfg; 1328173139Srwatson } 1329173139Srwatson __hal_serial_mem_write64(hldev, default_dtx_cfg[dtx_cnt], 1330173139Srwatson &bar0->dtx_control); 1331173139Srwatson dtx_cnt++; 1332173139Srwatson } 1333171095Ssam mdio_cfg: 1334173139Srwatson while (default_mdio_cfg[mdio_cnt] != END_SIGN) { 1335173139Srwatson if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { 1336173139Srwatson mdio_cnt++; 1337173139Srwatson goto dtx_cfg; 1338173139Srwatson } 1339173139Srwatson __hal_serial_mem_write64(hldev, default_mdio_cfg[mdio_cnt], 1340173139Srwatson &bar0->mdio_control); 1341173139Srwatson mdio_cnt++; 1342173139Srwatson } 1343171095Ssam } while ( !((default_dtx_cfg[dtx_cnt] == END_SIGN) && 1344173139Srwatson (default_mdio_cfg[mdio_cnt] == END_SIGN)) ); 1345171095Ssam 1346171095Ssam xge_debug_device(XGE_TRACE, "%s", "XAUI interface configured"); 1347171095Ssam} 1348171095Ssam 1349171095Ssam/* 1350171095Ssam * __hal_device_mac_link_util_set 1351171095Ssam * @hldev: HAL device handle. 1352171095Ssam * 1353171095Ssam * Set sampling rate to calculate link utilization. 1354171095Ssam */ 1355171095Ssamstatic void 1356171095Ssam__hal_device_mac_link_util_set(xge_hal_device_t *hldev) 1357171095Ssam{ 1358171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1359171095Ssam u64 val64; 1360171095Ssam 1361171095Ssam val64 = XGE_HAL_MAC_TX_LINK_UTIL_VAL( 1362173139Srwatson hldev->config.mac.tmac_util_period) | 1363173139Srwatson XGE_HAL_MAC_RX_LINK_UTIL_VAL( 1364173139Srwatson hldev->config.mac.rmac_util_period); 1365171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1366171095Ssam &bar0->mac_link_util); 1367171095Ssam xge_debug_device(XGE_TRACE, "%s", 1368173139Srwatson "bandwidth link utilization configured"); 1369171095Ssam} 1370171095Ssam 1371171095Ssam/* 1372171095Ssam * __hal_device_set_swapper 1373171095Ssam * @hldev: HAL device handle. 1374171095Ssam * 1375171095Ssam * Set the Xframe's byte "swapper" in accordance with 1376171095Ssam * endianness of the host. 1377171095Ssam */ 1378171095Ssamxge_hal_status_e 1379171095Ssam__hal_device_set_swapper(xge_hal_device_t *hldev) 1380171095Ssam{ 1381171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1382171095Ssam u64 val64; 1383171095Ssam 1384171095Ssam /* 1385171095Ssam * from 32bit errarta: 1386171095Ssam * 1387171095Ssam * The SWAPPER_CONTROL register determines how the adapter accesses 1388171095Ssam * host memory as well as how it responds to read and write requests 1389171095Ssam * from the host system. Writes to this register should be performed 1390171095Ssam * carefully, since the byte swappers could reverse the order of bytes. 1391171095Ssam * When configuring this register keep in mind that writes to the PIF 1392171095Ssam * read and write swappers could reverse the order of the upper and 1393171095Ssam * lower 32-bit words. This means that the driver may have to write 1394171095Ssam * to the upper 32 bits of the SWAPPER_CONTROL twice in order to 1395171095Ssam * configure the entire register. */ 1396171095Ssam 1397171095Ssam /* 1398171095Ssam * The device by default set to a big endian format, so a big endian 1399171095Ssam * driver need not set anything. 1400171095Ssam */ 1401171095Ssam 1402171095Ssam#if defined(XGE_HAL_CUSTOM_HW_SWAPPER) 1403171095Ssam 1404171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1405173139Srwatson 0xffffffffffffffffULL, &bar0->swapper_ctrl); 1406171095Ssam 1407171095Ssam val64 = XGE_HAL_CUSTOM_HW_SWAPPER; 1408171095Ssam 1409171095Ssam xge_os_wmb(); 1410171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1411173139Srwatson &bar0->swapper_ctrl); 1412171095Ssam 1413171095Ssam xge_debug_device(XGE_TRACE, "using custom HW swapper 0x"XGE_OS_LLXFMT, 1414173139Srwatson (unsigned long long)val64); 1415171095Ssam 1416171095Ssam#elif !defined(XGE_OS_HOST_BIG_ENDIAN) 1417171095Ssam 1418171095Ssam /* 1419171095Ssam * Initially we enable all bits to make it accessible by the driver, 1420171095Ssam * then we selectively enable only those bits that we want to set. 1421171095Ssam * i.e. force swapper to swap for the first time since second write 1422171095Ssam * will overwrite with the final settings. 1423171095Ssam * 1424171095Ssam * Use only for little endian platforms. 1425171095Ssam */ 1426171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1427173139Srwatson 0xffffffffffffffffULL, &bar0->swapper_ctrl); 1428171095Ssam xge_os_wmb(); 1429171095Ssam val64 = (XGE_HAL_SWAPPER_CTRL_PIF_R_FE | 1430173139Srwatson XGE_HAL_SWAPPER_CTRL_PIF_R_SE | 1431173139Srwatson XGE_HAL_SWAPPER_CTRL_PIF_W_FE | 1432173139Srwatson XGE_HAL_SWAPPER_CTRL_PIF_W_SE | 1433173139Srwatson XGE_HAL_SWAPPER_CTRL_RTH_FE | 1434173139Srwatson XGE_HAL_SWAPPER_CTRL_RTH_SE | 1435173139Srwatson XGE_HAL_SWAPPER_CTRL_TXP_FE | 1436173139Srwatson XGE_HAL_SWAPPER_CTRL_TXP_SE | 1437173139Srwatson XGE_HAL_SWAPPER_CTRL_TXD_R_FE | 1438173139Srwatson XGE_HAL_SWAPPER_CTRL_TXD_R_SE | 1439173139Srwatson XGE_HAL_SWAPPER_CTRL_TXD_W_FE | 1440173139Srwatson XGE_HAL_SWAPPER_CTRL_TXD_W_SE | 1441173139Srwatson XGE_HAL_SWAPPER_CTRL_TXF_R_FE | 1442173139Srwatson XGE_HAL_SWAPPER_CTRL_RXD_R_FE | 1443173139Srwatson XGE_HAL_SWAPPER_CTRL_RXD_R_SE | 1444173139Srwatson XGE_HAL_SWAPPER_CTRL_RXD_W_FE | 1445173139Srwatson XGE_HAL_SWAPPER_CTRL_RXD_W_SE | 1446173139Srwatson XGE_HAL_SWAPPER_CTRL_RXF_W_FE | 1447173139Srwatson XGE_HAL_SWAPPER_CTRL_XMSI_FE | 1448173139Srwatson XGE_HAL_SWAPPER_CTRL_STATS_FE | XGE_HAL_SWAPPER_CTRL_STATS_SE); 1449171095Ssam 1450171095Ssam /* 1451171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 1452173139Srwatson val64 |= XGE_HAL_SWAPPER_CTRL_XMSI_SE; 1453171095Ssam } */ 1454171095Ssam __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)val64, 1455171095Ssam &bar0->swapper_ctrl); 1456171095Ssam xge_os_wmb(); 1457171095Ssam __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), 1458171095Ssam &bar0->swapper_ctrl); 1459171095Ssam xge_os_wmb(); 1460171095Ssam __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), 1461171095Ssam &bar0->swapper_ctrl); 1462171095Ssam xge_debug_device(XGE_TRACE, "%s", "using little endian set"); 1463171095Ssam#endif 1464171095Ssam 1465171095Ssam /* Verifying if endian settings are accurate by reading a feedback 1466171095Ssam * register. */ 1467171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1468171095Ssam &bar0->pif_rd_swapper_fb); 1469171095Ssam if (val64 != XGE_HAL_IF_RD_SWAPPER_FB) { 1470173139Srwatson xge_debug_device(XGE_ERR, "pif_rd_swapper_fb read "XGE_OS_LLXFMT, 1471173139Srwatson (unsigned long long) val64); 1472173139Srwatson return XGE_HAL_ERR_SWAPPER_CTRL; 1473171095Ssam } 1474171095Ssam 1475171095Ssam xge_debug_device(XGE_TRACE, "%s", "be/le swapper enabled"); 1476171095Ssam 1477171095Ssam return XGE_HAL_OK; 1478171095Ssam} 1479171095Ssam 1480171095Ssam/* 1481171095Ssam * __hal_device_rts_mac_configure - Configure RTS steering based on 1482171095Ssam * destination mac address. 1483171095Ssam * @hldev: HAL device handle. 1484171095Ssam * 1485171095Ssam */ 1486171095Ssamxge_hal_status_e 1487171095Ssam__hal_device_rts_mac_configure(xge_hal_device_t *hldev) 1488171095Ssam{ 1489171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1490171095Ssam u64 val64; 1491171095Ssam 1492171095Ssam if (!hldev->config.rts_mac_en) { 1493173139Srwatson return XGE_HAL_OK; 1494171095Ssam } 1495171095Ssam 1496171095Ssam /* 1497171095Ssam * Set the receive traffic steering mode from default(classic) 1498171095Ssam * to enhanced. 1499171095Ssam */ 1500171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1501173139Srwatson &bar0->rts_ctrl); 1502171095Ssam val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 1503171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1504173139Srwatson val64, &bar0->rts_ctrl); 1505171095Ssam return XGE_HAL_OK; 1506171095Ssam} 1507171095Ssam 1508171095Ssam/* 1509171095Ssam * __hal_device_rts_port_configure - Configure RTS steering based on 1510171095Ssam * destination or source port number. 1511171095Ssam * @hldev: HAL device handle. 1512171095Ssam * 1513171095Ssam */ 1514171095Ssamxge_hal_status_e 1515171095Ssam__hal_device_rts_port_configure(xge_hal_device_t *hldev) 1516171095Ssam{ 1517171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1518171095Ssam u64 val64; 1519171095Ssam int rnum; 1520171095Ssam 1521171095Ssam if (!hldev->config.rts_port_en) { 1522173139Srwatson return XGE_HAL_OK; 1523171095Ssam } 1524171095Ssam 1525171095Ssam /* 1526171095Ssam * Set the receive traffic steering mode from default(classic) 1527171095Ssam * to enhanced. 1528171095Ssam */ 1529171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1530173139Srwatson &bar0->rts_ctrl); 1531171095Ssam val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 1532171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1533173139Srwatson val64, &bar0->rts_ctrl); 1534171095Ssam 1535171095Ssam /* 1536171095Ssam * Initiate port steering according to per-ring configuration 1537171095Ssam */ 1538171095Ssam for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) { 1539173139Srwatson int pnum; 1540173139Srwatson xge_hal_ring_queue_t *queue = &hldev->config.ring.queue[rnum]; 1541171095Ssam 1542173139Srwatson if (!queue->configured || queue->rts_port_en) 1543173139Srwatson continue; 1544171095Ssam 1545173139Srwatson for (pnum = 0; pnum < XGE_HAL_MAX_STEERABLE_PORTS; pnum++) { 1546173139Srwatson xge_hal_rts_port_t *port = &queue->rts_ports[pnum]; 1547171095Ssam 1548173139Srwatson /* 1549173139Srwatson * Skip and clear empty ports 1550173139Srwatson */ 1551173139Srwatson if (!port->num) { 1552173139Srwatson /* 1553173139Srwatson * Clear CAM memory 1554173139Srwatson */ 1555173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 1556173139Srwatson hldev->regh0, 0ULL, 1557173139Srwatson &bar0->rts_pn_cam_data); 1558171095Ssam 1559173139Srwatson val64 = BIT(7) | BIT(15); 1560173139Srwatson } else { 1561173139Srwatson /* 1562173139Srwatson * Assign new Port values according 1563173139Srwatson * to configuration 1564173139Srwatson */ 1565173139Srwatson val64 = vBIT(port->num,8,16) | 1566173139Srwatson vBIT(rnum,37,3) | BIT(63); 1567173139Srwatson if (port->src) 1568173139Srwatson val64 = BIT(47); 1569173139Srwatson if (!port->udp) 1570173139Srwatson val64 = BIT(7); 1571173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 1572173139Srwatson hldev->regh0, val64, 1573173139Srwatson &bar0->rts_pn_cam_data); 1574171095Ssam 1575173139Srwatson val64 = BIT(7) | BIT(15) | vBIT(pnum,24,8); 1576173139Srwatson } 1577171095Ssam 1578173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1579173139Srwatson val64, &bar0->rts_pn_cam_ctrl); 1580171095Ssam 1581173139Srwatson /* poll until done */ 1582173139Srwatson if (__hal_device_register_poll(hldev, 1583173139Srwatson &bar0->rts_pn_cam_ctrl, 0, 1584173139Srwatson XGE_HAL_RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED, 1585173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != 1586173139Srwatson XGE_HAL_OK) { 1587173139Srwatson /* upper layer may require to repeat */ 1588173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1589173139Srwatson } 1590173139Srwatson } 1591171095Ssam } 1592171095Ssam return XGE_HAL_OK; 1593171095Ssam} 1594171095Ssam 1595171095Ssam/* 1596171095Ssam * __hal_device_rts_qos_configure - Configure RTS steering based on 1597171095Ssam * qos. 1598171095Ssam * @hldev: HAL device handle. 1599171095Ssam * 1600171095Ssam */ 1601171095Ssamxge_hal_status_e 1602171095Ssam__hal_device_rts_qos_configure(xge_hal_device_t *hldev) 1603171095Ssam{ 1604171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1605171095Ssam u64 val64; 1606171095Ssam int j, rx_ring_num; 1607171095Ssam 1608171095Ssam if (!hldev->config.rts_qos_en) { 1609173139Srwatson return XGE_HAL_OK; 1610171095Ssam } 1611171095Ssam 1612171095Ssam /* First clear the RTS_DS_MEM_DATA */ 1613171095Ssam val64 = 0; 1614171095Ssam for (j = 0; j < 64; j++ ) 1615171095Ssam { 1616173139Srwatson /* First clear the value */ 1617173139Srwatson val64 = XGE_HAL_RTS_DS_MEM_DATA(0); 1618171095Ssam 1619173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1620173139Srwatson &bar0->rts_ds_mem_data); 1621171095Ssam 1622173139Srwatson val64 = XGE_HAL_RTS_DS_MEM_CTRL_WE | 1623173139Srwatson XGE_HAL_RTS_DS_MEM_CTRL_STROBE_NEW_CMD | 1624173139Srwatson XGE_HAL_RTS_DS_MEM_CTRL_OFFSET ( j ); 1625171095Ssam 1626173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1627173139Srwatson &bar0->rts_ds_mem_ctrl); 1628171095Ssam 1629171095Ssam 1630173139Srwatson /* poll until done */ 1631173139Srwatson if (__hal_device_register_poll(hldev, 1632173139Srwatson &bar0->rts_ds_mem_ctrl, 0, 1633173139Srwatson XGE_HAL_RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED, 1634173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1635173139Srwatson /* upper layer may require to repeat */ 1636173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1637173139Srwatson } 1638171095Ssam 1639171095Ssam } 1640171095Ssam 1641171095Ssam rx_ring_num = 0; 1642171095Ssam for (j = 0; j < XGE_HAL_MAX_RING_NUM; j++) { 1643173139Srwatson if (hldev->config.ring.queue[j].configured) 1644173139Srwatson rx_ring_num++; 1645171095Ssam } 1646171095Ssam 1647171095Ssam switch (rx_ring_num) { 1648171095Ssam case 1: 1649173139Srwatson val64 = 0x0; 1650173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1651173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1652173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1653173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1654173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1655173139Srwatson break; 1656171095Ssam case 2: 1657173139Srwatson val64 = 0x0001000100010001ULL; 1658173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1659173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1660173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1661173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1662173139Srwatson val64 = 0x0001000100000000ULL; 1663173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1664173139Srwatson break; 1665171095Ssam case 3: 1666173139Srwatson val64 = 0x0001020001020001ULL; 1667173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1668173139Srwatson val64 = 0x0200010200010200ULL; 1669173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1670173139Srwatson val64 = 0x0102000102000102ULL; 1671173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1672173139Srwatson val64 = 0x0001020001020001ULL; 1673173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1674173139Srwatson val64 = 0x0200010200000000ULL; 1675173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1676173139Srwatson break; 1677171095Ssam case 4: 1678173139Srwatson val64 = 0x0001020300010203ULL; 1679173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1680173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1681173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1682173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1683173139Srwatson val64 = 0x0001020300000000ULL; 1684173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1685173139Srwatson break; 1686171095Ssam case 5: 1687173139Srwatson val64 = 0x0001020304000102ULL; 1688173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1689173139Srwatson val64 = 0x0304000102030400ULL; 1690173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1691173139Srwatson val64 = 0x0102030400010203ULL; 1692173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1693173139Srwatson val64 = 0x0400010203040001ULL; 1694173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1695173139Srwatson val64 = 0x0203040000000000ULL; 1696173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1697173139Srwatson break; 1698171095Ssam case 6: 1699173139Srwatson val64 = 0x0001020304050001ULL; 1700173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1701173139Srwatson val64 = 0x0203040500010203ULL; 1702173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1703173139Srwatson val64 = 0x0405000102030405ULL; 1704173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1705173139Srwatson val64 = 0x0001020304050001ULL; 1706173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1707173139Srwatson val64 = 0x0203040500000000ULL; 1708173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1709173139Srwatson break; 1710171095Ssam case 7: 1711173139Srwatson val64 = 0x0001020304050600ULL; 1712173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1713173139Srwatson val64 = 0x0102030405060001ULL; 1714173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1715173139Srwatson val64 = 0x0203040506000102ULL; 1716173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1717173139Srwatson val64 = 0x0304050600010203ULL; 1718173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1719173139Srwatson val64 = 0x0405060000000000ULL; 1720173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1721173139Srwatson break; 1722171095Ssam case 8: 1723173139Srwatson val64 = 0x0001020304050607ULL; 1724173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 1725173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 1726173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 1727173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 1728173139Srwatson val64 = 0x0001020300000000ULL; 1729173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 1730173139Srwatson break; 1731171095Ssam } 1732171095Ssam 1733171095Ssam return XGE_HAL_OK; 1734171095Ssam} 1735171095Ssam 1736171095Ssam/* 1737171095Ssam * xge__hal_device_rts_mac_enable 1738171095Ssam * 1739171095Ssam * @devh: HAL device handle. 1740171095Ssam * @index: index number where the MAC addr will be stored 1741171095Ssam * @macaddr: MAC address 1742171095Ssam * 1743171095Ssam * - Enable RTS steering for the given MAC address. This function has to be 1744171095Ssam * called with lock acquired. 1745171095Ssam * 1746171095Ssam * NOTE: 1747171095Ssam * 1. ULD has to call this function with the index value which 1748171095Ssam * statisfies the following condition: 1749173139Srwatson * ring_num = (index % 8) 1750171095Ssam * 2.ULD also needs to make sure that the index is not 1751171095Ssam * occupied by any MAC address. If that index has any MAC address 1752171095Ssam * it will be overwritten and HAL will not check for it. 1753171095Ssam * 1754171095Ssam */ 1755171095Ssamxge_hal_status_e 1756171095Ssamxge_hal_device_rts_mac_enable(xge_hal_device_h devh, int index, macaddr_t macaddr) 1757171095Ssam{ 1758171095Ssam int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; 1759171095Ssam xge_hal_status_e status; 1760171095Ssam 1761171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 1762171095Ssam 1763171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 1764173139Srwatson max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; 1765171095Ssam 1766171095Ssam if ( index >= max_addr ) 1767173139Srwatson return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 1768171095Ssam 1769171095Ssam /* 1770171095Ssam * Set the MAC address at the given location marked by index. 1771171095Ssam */ 1772171095Ssam status = xge_hal_device_macaddr_set(hldev, index, macaddr); 1773171095Ssam if (status != XGE_HAL_OK) { 1774173139Srwatson xge_debug_device(XGE_ERR, "%s", 1775173139Srwatson "Not able to set the mac addr"); 1776173139Srwatson return status; 1777171095Ssam } 1778171095Ssam 1779171095Ssam return xge_hal_device_rts_section_enable(hldev, index); 1780171095Ssam} 1781171095Ssam 1782171095Ssam/* 1783171095Ssam * xge__hal_device_rts_mac_disable 1784171095Ssam * @hldev: HAL device handle. 1785171095Ssam * @index: index number where to disable the MAC addr 1786171095Ssam * 1787171095Ssam * Disable RTS Steering based on the MAC address. 1788171095Ssam * This function should be called with lock acquired. 1789171095Ssam * 1790171095Ssam */ 1791171095Ssamxge_hal_status_e 1792171095Ssamxge_hal_device_rts_mac_disable(xge_hal_device_h devh, int index) 1793171095Ssam{ 1794171095Ssam xge_hal_status_e status; 1795171095Ssam u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 1796171095Ssam int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; 1797171095Ssam 1798171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 1799171095Ssam 1800171095Ssam xge_debug_ll(XGE_TRACE, "the index value is %d ", index); 1801171095Ssam 1802171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 1803173139Srwatson max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; 1804171095Ssam 1805171095Ssam if ( index >= max_addr ) 1806173139Srwatson return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 1807171095Ssam 1808171095Ssam /* 1809171095Ssam * Disable MAC address @ given index location 1810171095Ssam */ 1811171095Ssam status = xge_hal_device_macaddr_set(hldev, index, macaddr); 1812171095Ssam if (status != XGE_HAL_OK) { 1813173139Srwatson xge_debug_device(XGE_ERR, "%s", 1814173139Srwatson "Not able to set the mac addr"); 1815173139Srwatson return status; 1816171095Ssam } 1817171095Ssam 1818171095Ssam return XGE_HAL_OK; 1819171095Ssam} 1820171095Ssam 1821171095Ssam 1822171095Ssam/* 1823171095Ssam * __hal_device_rth_configure - Configure RTH for the device 1824171095Ssam * @hldev: HAL device handle. 1825171095Ssam * 1826171095Ssam * Using IT (Indirection Table). 1827171095Ssam */ 1828171095Ssamxge_hal_status_e 1829171095Ssam__hal_device_rth_it_configure(xge_hal_device_t *hldev) 1830171095Ssam{ 1831171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1832171095Ssam u64 val64; 1833171095Ssam int rings[XGE_HAL_MAX_RING_NUM]={0}; 1834171095Ssam int rnum; 1835171095Ssam int rmax; 1836171095Ssam int buckets_num; 1837171095Ssam int bucket; 1838171095Ssam 1839171095Ssam if (!hldev->config.rth_en) { 1840173139Srwatson return XGE_HAL_OK; 1841171095Ssam } 1842171095Ssam 1843171095Ssam /* 1844171095Ssam * Set the receive traffic steering mode from default(classic) 1845171095Ssam * to enhanced. 1846171095Ssam */ 1847171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1848173139Srwatson &bar0->rts_ctrl); 1849171095Ssam val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 1850171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1851173139Srwatson val64, &bar0->rts_ctrl); 1852171095Ssam 1853171095Ssam buckets_num = (1 << hldev->config.rth_bucket_size); 1854171095Ssam 1855171095Ssam rmax=0; 1856171095Ssam for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) { 1857173139Srwatson if (hldev->config.ring.queue[rnum].configured && 1858173139Srwatson hldev->config.ring.queue[rnum].rth_en) 1859173139Srwatson rings[rmax++] = rnum; 1860171095Ssam } 1861171095Ssam 1862171095Ssam rnum = 0; 1863171095Ssam /* for starters: fill in all the buckets with rings "equally" */ 1864171095Ssam for (bucket = 0; bucket < buckets_num; bucket++) { 1865171095Ssam 1866171095Ssam if (rnum == rmax) 1867173139Srwatson rnum = 0; 1868171095Ssam 1869173139Srwatson /* write data */ 1870173139Srwatson val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN | 1871173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_DATA(rings[rnum]); 1872173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1873173139Srwatson &bar0->rts_rth_map_mem_data); 1874171095Ssam 1875173139Srwatson /* execute */ 1876173139Srwatson val64 = XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE | 1877173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE | 1878173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(bucket); 1879173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1880173139Srwatson &bar0->rts_rth_map_mem_ctrl); 1881171095Ssam 1882173139Srwatson /* poll until done */ 1883173139Srwatson if (__hal_device_register_poll(hldev, 1884173139Srwatson &bar0->rts_rth_map_mem_ctrl, 0, 1885173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE, 1886173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1887173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1888173139Srwatson } 1889171095Ssam 1890173139Srwatson rnum++; 1891171095Ssam } 1892171095Ssam 1893171095Ssam val64 = XGE_HAL_RTS_RTH_EN; 1894171095Ssam val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(hldev->config.rth_bucket_size); 1895171095Ssam val64 |= XGE_HAL_RTS_RTH_TCP_IPV4_EN | XGE_HAL_RTS_RTH_UDP_IPV4_EN | XGE_HAL_RTS_RTH_IPV4_EN | 1896173139Srwatson XGE_HAL_RTS_RTH_TCP_IPV6_EN |XGE_HAL_RTS_RTH_UDP_IPV6_EN | XGE_HAL_RTS_RTH_IPV6_EN | 1897173139Srwatson XGE_HAL_RTS_RTH_TCP_IPV6_EX_EN | XGE_HAL_RTS_RTH_UDP_IPV6_EX_EN | XGE_HAL_RTS_RTH_IPV6_EX_EN; 1898171095Ssam 1899171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1900173139Srwatson &bar0->rts_rth_cfg); 1901171095Ssam 1902171095Ssam xge_debug_device(XGE_TRACE, "RTH configured, bucket_size %d", 1903173139Srwatson hldev->config.rth_bucket_size); 1904171095Ssam 1905171095Ssam return XGE_HAL_OK; 1906171095Ssam} 1907171095Ssam 1908171095Ssam 1909171095Ssam/* 1910171095Ssam * __hal_spdm_entry_add - Add a new entry to the SPDM table. 1911171095Ssam * 1912171095Ssam * Add a new entry to the SPDM table 1913171095Ssam * 1914171095Ssam * This function add a new entry to the SPDM table. 1915171095Ssam * 1916171095Ssam * Note: 1917171095Ssam * This function should be called with spdm_lock. 1918171095Ssam * 1919171095Ssam * See also: xge_hal_spdm_entry_add , xge_hal_spdm_entry_remove. 1920171095Ssam */ 1921171095Ssamstatic xge_hal_status_e 1922171095Ssam__hal_spdm_entry_add(xge_hal_device_t *hldev, xge_hal_ipaddr_t *src_ip, 1923173139Srwatson xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, u8 is_tcp, 1924173139Srwatson u8 is_ipv4, u8 tgt_queue, u32 jhash_value, u16 spdm_entry) 1925171095Ssam{ 1926171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1927171095Ssam u64 val64; 1928171095Ssam u64 spdm_line_arr[8]; 1929171095Ssam u8 line_no; 1930171095Ssam 1931171095Ssam /* 1932171095Ssam * Clear the SPDM READY bit 1933171095Ssam */ 1934171095Ssam val64 = XGE_HAL_RX_PIC_INT_REG_SPDM_READY; 1935171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1936173139Srwatson &bar0->rxpic_int_reg); 1937171095Ssam 1938171095Ssam xge_debug_device(XGE_TRACE, 1939173139Srwatson "L4 SP %x:DP %x: hash %x tgt_queue %d ", 1940173139Srwatson l4_sp, l4_dp, jhash_value, tgt_queue); 1941171095Ssam 1942171095Ssam xge_os_memzero(&spdm_line_arr, sizeof(spdm_line_arr)); 1943171095Ssam 1944171095Ssam /* 1945171095Ssam * Construct the SPDM entry. 1946171095Ssam */ 1947171095Ssam spdm_line_arr[0] = vBIT(l4_sp,0,16) | 1948173139Srwatson vBIT(l4_dp,16,32) | 1949173139Srwatson vBIT(tgt_queue,53,3) | 1950173139Srwatson vBIT(is_tcp,59,1) | 1951173139Srwatson vBIT(is_ipv4,63,1); 1952171095Ssam 1953171095Ssam 1954171095Ssam if (is_ipv4) { 1955173139Srwatson spdm_line_arr[1] = vBIT(src_ip->ipv4.addr,0,32) | 1956173139Srwatson vBIT(dst_ip->ipv4.addr,32,32); 1957171095Ssam 1958171095Ssam } else { 1959173139Srwatson xge_os_memcpy(&spdm_line_arr[1], &src_ip->ipv6.addr[0], 8); 1960173139Srwatson xge_os_memcpy(&spdm_line_arr[2], &src_ip->ipv6.addr[1], 8); 1961173139Srwatson xge_os_memcpy(&spdm_line_arr[3], &dst_ip->ipv6.addr[0], 8); 1962173139Srwatson xge_os_memcpy(&spdm_line_arr[4], &dst_ip->ipv6.addr[1], 8); 1963171095Ssam } 1964171095Ssam 1965171095Ssam spdm_line_arr[7] = vBIT(jhash_value,0,32) | 1966173139Srwatson BIT(63); /* entry enable bit */ 1967171095Ssam 1968171095Ssam /* 1969171095Ssam * Add the entry to the SPDM table 1970171095Ssam */ 1971171095Ssam for(line_no = 0; line_no < 8; line_no++) { 1972173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1973173139Srwatson spdm_line_arr[line_no], 1974173139Srwatson (void *)((char *)hldev->spdm_mem_base + 1975173139Srwatson (spdm_entry * 64) + 1976173139Srwatson (line_no * 8))); 1977171095Ssam } 1978171095Ssam 1979171095Ssam /* 1980171095Ssam * Wait for the operation to be completed. 1981171095Ssam */ 1982171095Ssam if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1, 1983173139Srwatson XGE_HAL_RX_PIC_INT_REG_SPDM_READY, 1984173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1985173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1986171095Ssam } 1987171095Ssam 1988171095Ssam /* 1989171095Ssam * Add this information to a local SPDM table. The purpose of 1990171095Ssam * maintaining a local SPDM table is to avoid a search in the 1991171095Ssam * adapter SPDM table for spdm entry lookup which is very costly 1992171095Ssam * in terms of time. 1993171095Ssam */ 1994171095Ssam hldev->spdm_table[spdm_entry]->in_use = 1; 1995171095Ssam xge_os_memcpy(&hldev->spdm_table[spdm_entry]->src_ip, src_ip, 1996173139Srwatson sizeof(xge_hal_ipaddr_t)); 1997171095Ssam xge_os_memcpy(&hldev->spdm_table[spdm_entry]->dst_ip, dst_ip, 1998173139Srwatson sizeof(xge_hal_ipaddr_t)); 1999171095Ssam hldev->spdm_table[spdm_entry]->l4_sp = l4_sp; 2000171095Ssam hldev->spdm_table[spdm_entry]->l4_dp = l4_dp; 2001171095Ssam hldev->spdm_table[spdm_entry]->is_tcp = is_tcp; 2002171095Ssam hldev->spdm_table[spdm_entry]->is_ipv4 = is_ipv4; 2003171095Ssam hldev->spdm_table[spdm_entry]->tgt_queue = tgt_queue; 2004171095Ssam hldev->spdm_table[spdm_entry]->jhash_value = jhash_value; 2005171095Ssam hldev->spdm_table[spdm_entry]->spdm_entry = spdm_entry; 2006171095Ssam 2007171095Ssam return XGE_HAL_OK; 2008171095Ssam} 2009171095Ssam 2010171095Ssam/* 2011171095Ssam * __hal_device_rth_spdm_configure - Configure RTH for the device 2012171095Ssam * @hldev: HAL device handle. 2013171095Ssam * 2014171095Ssam * Using SPDM (Socket-Pair Direct Match). 2015171095Ssam */ 2016171095Ssamxge_hal_status_e 2017171095Ssam__hal_device_rth_spdm_configure(xge_hal_device_t *hldev) 2018171095Ssam{ 2019171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 2020171095Ssam u64 val64; 2021171095Ssam u8 spdm_bar_num; 2022171095Ssam u32 spdm_bar_offset; 2023171095Ssam int spdm_table_size; 2024171095Ssam int i; 2025171095Ssam 2026171095Ssam if (!hldev->config.rth_spdm_en) { 2027173139Srwatson return XGE_HAL_OK; 2028171095Ssam } 2029171095Ssam 2030171095Ssam /* 2031171095Ssam * Retrieve the base address of SPDM Table. 2032171095Ssam */ 2033171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, 2034173139Srwatson hldev->regh0, &bar0->spdm_bir_offset); 2035171095Ssam 2036173139Srwatson spdm_bar_num = XGE_HAL_SPDM_PCI_BAR_NUM(val64); 2037173139Srwatson spdm_bar_offset = XGE_HAL_SPDM_PCI_BAR_OFFSET(val64); 2038171095Ssam 2039171095Ssam 2040171095Ssam /* 2041171095Ssam * spdm_bar_num specifies the PCI bar num register used to 2042171095Ssam * address the memory space. spdm_bar_offset specifies the offset 2043171095Ssam * of the SPDM memory with in the bar num memory space. 2044171095Ssam */ 2045171095Ssam switch (spdm_bar_num) { 2046173139Srwatson case 0: 2047173139Srwatson { 2048173139Srwatson hldev->spdm_mem_base = (char *)bar0 + 2049173139Srwatson (spdm_bar_offset * 8); 2050173139Srwatson break; 2051173139Srwatson } 2052173139Srwatson case 1: 2053173139Srwatson { 2054173139Srwatson char *bar1 = (char *)hldev->bar1; 2055173139Srwatson hldev->spdm_mem_base = bar1 + (spdm_bar_offset * 8); 2056173139Srwatson break; 2057173139Srwatson } 2058173139Srwatson default: 2059173139Srwatson xge_assert(((spdm_bar_num != 0) && (spdm_bar_num != 1))); 2060171095Ssam } 2061171095Ssam 2062171095Ssam /* 2063171095Ssam * Retrieve the size of SPDM table(number of entries). 2064171095Ssam */ 2065171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, 2066173139Srwatson hldev->regh0, &bar0->spdm_structure); 2067171095Ssam hldev->spdm_max_entries = XGE_HAL_SPDM_MAX_ENTRIES(val64); 2068171095Ssam 2069171095Ssam 2070171095Ssam spdm_table_size = hldev->spdm_max_entries * 2071173139Srwatson sizeof(xge_hal_spdm_entry_t); 2072171095Ssam if (hldev->spdm_table == NULL) { 2073173139Srwatson void *mem; 2074171095Ssam 2075173139Srwatson /* 2076173139Srwatson * Allocate memory to hold the copy of SPDM table. 2077173139Srwatson */ 2078173139Srwatson if ((hldev->spdm_table = (xge_hal_spdm_entry_t **) 2079173139Srwatson xge_os_malloc( 2080173139Srwatson hldev->pdev, 2081173139Srwatson (sizeof(xge_hal_spdm_entry_t *) * 2082173139Srwatson hldev->spdm_max_entries))) == NULL) { 2083173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 2084173139Srwatson } 2085171095Ssam 2086173139Srwatson if ((mem = xge_os_malloc(hldev->pdev, spdm_table_size)) == NULL) 2087173139Srwatson { 2088173139Srwatson xge_os_free(hldev->pdev, hldev->spdm_table, 2089173139Srwatson (sizeof(xge_hal_spdm_entry_t *) * 2090173139Srwatson hldev->spdm_max_entries)); 2091173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 2092173139Srwatson } 2093171095Ssam 2094173139Srwatson xge_os_memzero(mem, spdm_table_size); 2095173139Srwatson for (i = 0; i < hldev->spdm_max_entries; i++) { 2096173139Srwatson hldev->spdm_table[i] = (xge_hal_spdm_entry_t *) 2097173139Srwatson ((char *)mem + 2098173139Srwatson i * sizeof(xge_hal_spdm_entry_t)); 2099173139Srwatson } 2100173139Srwatson xge_os_spin_lock_init(&hldev->spdm_lock, hldev->pdev); 2101171095Ssam } else { 2102173139Srwatson /* 2103173139Srwatson * We are here because the host driver tries to 2104173139Srwatson * do a soft reset on the device. 2105173139Srwatson * Since the device soft reset clears the SPDM table, copy 2106173139Srwatson * the entries from the local SPDM table to the actual one. 2107173139Srwatson */ 2108173139Srwatson xge_os_spin_lock(&hldev->spdm_lock); 2109173139Srwatson for (i = 0; i < hldev->spdm_max_entries; i++) { 2110173139Srwatson xge_hal_spdm_entry_t *spdm_entry = hldev->spdm_table[i]; 2111171095Ssam 2112173139Srwatson if (spdm_entry->in_use) { 2113173139Srwatson if (__hal_spdm_entry_add(hldev, 2114173139Srwatson &spdm_entry->src_ip, 2115173139Srwatson &spdm_entry->dst_ip, 2116173139Srwatson spdm_entry->l4_sp, 2117173139Srwatson spdm_entry->l4_dp, 2118173139Srwatson spdm_entry->is_tcp, 2119173139Srwatson spdm_entry->is_ipv4, 2120173139Srwatson spdm_entry->tgt_queue, 2121173139Srwatson spdm_entry->jhash_value, 2122173139Srwatson spdm_entry->spdm_entry) 2123173139Srwatson != XGE_HAL_OK) { 2124173139Srwatson /* Log an warning */ 2125173139Srwatson xge_debug_device(XGE_ERR, 2126173139Srwatson "SPDM table update from local" 2127173139Srwatson " memory failed"); 2128173139Srwatson } 2129173139Srwatson } 2130173139Srwatson } 2131173139Srwatson xge_os_spin_unlock(&hldev->spdm_lock); 2132171095Ssam } 2133171095Ssam 2134171095Ssam /* 2135171095Ssam * Set the receive traffic steering mode from default(classic) 2136171095Ssam * to enhanced. 2137171095Ssam */ 2138171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, 2139173139Srwatson hldev->regh0, &bar0->rts_ctrl); 2140171095Ssam val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 2141171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2142173139Srwatson val64, &bar0->rts_ctrl); 2143171095Ssam 2144171095Ssam /* 2145171095Ssam * We may not need to configure rts_rth_jhash_cfg register as the 2146171095Ssam * default values are good enough to calculate the hash. 2147171095Ssam */ 2148171095Ssam 2149171095Ssam /* 2150171095Ssam * As of now, set all the rth mask registers to zero. TODO. 2151171095Ssam */ 2152171095Ssam for(i = 0; i < 5; i++) { 2153173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2154173139Srwatson 0, &bar0->rts_rth_hash_mask[i]); 2155171095Ssam } 2156171095Ssam 2157171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2158173139Srwatson 0, &bar0->rts_rth_hash_mask_5); 2159171095Ssam 2160171095Ssam if (hldev->config.rth_spdm_use_l4) { 2161173139Srwatson val64 = XGE_HAL_RTH_STATUS_SPDM_USE_L4; 2162173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2163173139Srwatson val64, &bar0->rts_rth_status); 2164171095Ssam } 2165171095Ssam 2166171095Ssam val64 = XGE_HAL_RTS_RTH_EN; 2167171095Ssam val64 |= XGE_HAL_RTS_RTH_IPV4_EN | XGE_HAL_RTS_RTH_TCP_IPV4_EN; 2168171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2169173139Srwatson &bar0->rts_rth_cfg); 2170171095Ssam 2171171095Ssam 2172171095Ssam return XGE_HAL_OK; 2173171095Ssam} 2174171095Ssam 2175171095Ssam/* 2176171095Ssam * __hal_device_pci_init 2177171095Ssam * @hldev: HAL device handle. 2178171095Ssam * 2179171095Ssam * Initialize certain PCI/PCI-X configuration registers 2180171095Ssam * with recommended values. Save config space for future hw resets. 2181171095Ssam */ 2182171095Ssamstatic void 2183171095Ssam__hal_device_pci_init(xge_hal_device_t *hldev) 2184171095Ssam{ 2185171095Ssam int i, pcisize = 0; 2186171095Ssam u16 cmd = 0; 2187171095Ssam u8 val; 2188171095Ssam 2189171095Ssam /* Store PCI device ID and revision for future references where in we 2190171095Ssam * decide Xena revision using PCI sub system ID */ 2191171095Ssam xge_os_pci_read16(hldev->pdev,hldev->cfgh, 2192173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, device_id), 2193173139Srwatson &hldev->device_id); 2194171095Ssam xge_os_pci_read8(hldev->pdev,hldev->cfgh, 2195173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, revision), 2196173139Srwatson &hldev->revision); 2197171095Ssam 2198171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 2199173139Srwatson pcisize = XGE_HAL_PCISIZE_HERC; 2200171095Ssam else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 2201173139Srwatson pcisize = XGE_HAL_PCISIZE_XENA; 2202171095Ssam 2203171095Ssam /* save original PCI config space to restore it on device_terminate() */ 2204171095Ssam for (i = 0; i < pcisize; i++) { 2205173139Srwatson xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, 2206173139Srwatson (u32*)&hldev->pci_config_space_bios + i); 2207171095Ssam } 2208171095Ssam 2209171095Ssam /* Set the PErr Repconse bit and SERR in PCI command register. */ 2210171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2211173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); 2212171095Ssam cmd |= 0x140; 2213171095Ssam xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2214173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, command), cmd); 2215171095Ssam 2216171095Ssam /* Set user spcecified value for the PCI Latency Timer */ 2217171095Ssam if (hldev->config.latency_timer && 2218171095Ssam hldev->config.latency_timer != XGE_HAL_USE_BIOS_DEFAULT_LATENCY) { 2219173139Srwatson xge_os_pci_write8(hldev->pdev, hldev->cfgh, 2220171095Ssam xge_offsetof(xge_hal_pci_config_le_t, 2221171095Ssam latency_timer), 2222173139Srwatson (u8)hldev->config.latency_timer); 2223171095Ssam } 2224171095Ssam /* Read back latency timer to reflect it into user level */ 2225171095Ssam xge_os_pci_read8(hldev->pdev, hldev->cfgh, 2226173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, latency_timer), &val); 2227171095Ssam hldev->config.latency_timer = val; 2228171095Ssam 2229171095Ssam /* Enable Data Parity Error Recovery in PCI-X command register. */ 2230171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2231173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); 2232171095Ssam cmd |= 1; 2233171095Ssam xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2234173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd); 2235171095Ssam 2236171095Ssam /* Set MMRB count in PCI-X command register. */ 2237171095Ssam if (hldev->config.mmrb_count != XGE_HAL_DEFAULT_BIOS_MMRB_COUNT) { 2238173139Srwatson cmd &= 0xFFF3; 2239173139Srwatson cmd |= hldev->config.mmrb_count << 2; 2240173139Srwatson xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2241173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2242173139Srwatson cmd); 2243171095Ssam } 2244171095Ssam /* Read back MMRB count to reflect it into user level */ 2245171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2246173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2247173139Srwatson &cmd); 2248171095Ssam cmd &= 0x000C; 2249171095Ssam hldev->config.mmrb_count = cmd>>2; 2250171095Ssam 2251171095Ssam /* Setting Maximum outstanding splits based on system type. */ 2252171095Ssam if (hldev->config.max_splits_trans != XGE_HAL_USE_BIOS_DEFAULT_SPLITS) { 2253173139Srwatson xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2254173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2255173139Srwatson &cmd); 2256173139Srwatson cmd &= 0xFF8F; 2257173139Srwatson cmd |= hldev->config.max_splits_trans << 4; 2258173139Srwatson xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2259173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2260173139Srwatson cmd); 2261171095Ssam } 2262171095Ssam 2263171095Ssam /* Read back max split trans to reflect it into user level */ 2264171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2265173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); 2266171095Ssam cmd &= 0x0070; 2267171095Ssam hldev->config.max_splits_trans = cmd>>4; 2268171095Ssam 2269171095Ssam /* Forcibly disabling relaxed ordering capability of the card. */ 2270171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2271173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); 2272171095Ssam cmd &= 0xFFFD; 2273171095Ssam xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2274173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd); 2275171095Ssam 2276171095Ssam /* save PCI config space for future resets */ 2277171095Ssam for (i = 0; i < pcisize; i++) { 2278173139Srwatson xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, 2279173139Srwatson (u32*)&hldev->pci_config_space + i); 2280171095Ssam } 2281171095Ssam} 2282171095Ssam 2283171095Ssam/* 2284171095Ssam * __hal_device_pci_info_get - Get PCI bus informations such as width, frequency 2285171095Ssam * and mode. 2286171095Ssam * @devh: HAL device handle. 2287173139Srwatson * @pci_mode: pointer to a variable of enumerated type 2288173139Srwatson * xge_hal_pci_mode_e{}. 2289173139Srwatson * @bus_frequency: pointer to a variable of enumerated type 2290173139Srwatson * xge_hal_pci_bus_frequency_e{}. 2291173139Srwatson * @bus_width: pointer to a variable of enumerated type 2292173139Srwatson * xge_hal_pci_bus_width_e{}. 2293171095Ssam * 2294171095Ssam * Get pci mode, frequency, and PCI bus width. 2295171095Ssam * 2296171095Ssam * Returns: one of the xge_hal_status_e{} enumerated types. 2297173139Srwatson * XGE_HAL_OK - for success. 2298171095Ssam * XGE_HAL_ERR_INVALID_PCI_INFO - for invalid PCI information from the card. 2299173139Srwatson * XGE_HAL_ERR_BAD_DEVICE_ID - for invalid card. 2300171095Ssam * 2301171095Ssam * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e. 2302171095Ssam */ 2303171095Ssamstatic xge_hal_status_e 2304171095Ssam__hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, 2305173139Srwatson xge_hal_pci_bus_frequency_e *bus_frequency, 2306173139Srwatson xge_hal_pci_bus_width_e *bus_width) 2307171095Ssam{ 2308171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 2309171095Ssam xge_hal_status_e rc_status = XGE_HAL_OK; 2310173139Srwatson xge_hal_card_e card_id = xge_hal_device_check_id (devh); 2311171095Ssam 2312171095Ssam#ifdef XGE_HAL_HERC_EMULATION 2313171095Ssam hldev->config.pci_freq_mherz = 2314173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2315173139Srwatson *bus_frequency = 2316173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2317171095Ssam *pci_mode = XGE_HAL_PCI_66MHZ_MODE; 2318171095Ssam#else 2319171095Ssam if (card_id == XGE_HAL_CARD_HERC) { 2320173139Srwatson xge_hal_pci_bar0_t *bar0 = 2321173139Srwatson (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2322173139Srwatson u64 pci_info = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2323173139Srwatson &bar0->pci_info); 2324173139Srwatson if (XGE_HAL_PCI_32_BIT & pci_info) 2325173139Srwatson *bus_width = XGE_HAL_PCI_BUS_WIDTH_32BIT; 2326173139Srwatson else 2327173139Srwatson *bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT; 2328173139Srwatson switch((pci_info & XGE_HAL_PCI_INFO)>>60) 2329173139Srwatson { 2330173139Srwatson case XGE_HAL_PCI_33MHZ_MODE: 2331173139Srwatson *bus_frequency = 2332173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_33MHZ; 2333173139Srwatson *pci_mode = XGE_HAL_PCI_33MHZ_MODE; 2334173139Srwatson break; 2335173139Srwatson case XGE_HAL_PCI_66MHZ_MODE: 2336173139Srwatson *bus_frequency = 2337173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2338173139Srwatson *pci_mode = XGE_HAL_PCI_66MHZ_MODE; 2339173139Srwatson break; 2340173139Srwatson case XGE_HAL_PCIX_M1_66MHZ_MODE: 2341173139Srwatson *bus_frequency = 2342173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2343173139Srwatson *pci_mode = XGE_HAL_PCIX_M1_66MHZ_MODE; 2344173139Srwatson break; 2345173139Srwatson case XGE_HAL_PCIX_M1_100MHZ_MODE: 2346173139Srwatson *bus_frequency = 2347173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_100MHZ; 2348173139Srwatson *pci_mode = XGE_HAL_PCIX_M1_100MHZ_MODE; 2349173139Srwatson break; 2350173139Srwatson case XGE_HAL_PCIX_M1_133MHZ_MODE: 2351173139Srwatson *bus_frequency = 2352173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; 2353173139Srwatson *pci_mode = XGE_HAL_PCIX_M1_133MHZ_MODE; 2354173139Srwatson break; 2355173139Srwatson case XGE_HAL_PCIX_M2_66MHZ_MODE: 2356173139Srwatson *bus_frequency = 2357173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; 2358173139Srwatson *pci_mode = XGE_HAL_PCIX_M2_66MHZ_MODE; 2359173139Srwatson break; 2360173139Srwatson case XGE_HAL_PCIX_M2_100MHZ_MODE: 2361173139Srwatson *bus_frequency = 2362173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_200MHZ; 2363173139Srwatson *pci_mode = XGE_HAL_PCIX_M2_100MHZ_MODE; 2364173139Srwatson break; 2365173139Srwatson case XGE_HAL_PCIX_M2_133MHZ_MODE: 2366173139Srwatson *bus_frequency = 2367173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_266MHZ; 2368173139Srwatson *pci_mode = XGE_HAL_PCIX_M2_133MHZ_MODE; 2369173139Srwatson break; 2370173139Srwatson case XGE_HAL_PCIX_M1_RESERVED: 2371173139Srwatson case XGE_HAL_PCIX_M1_66MHZ_NS: 2372173139Srwatson case XGE_HAL_PCIX_M1_100MHZ_NS: 2373173139Srwatson case XGE_HAL_PCIX_M1_133MHZ_NS: 2374173139Srwatson case XGE_HAL_PCIX_M2_RESERVED: 2375173139Srwatson case XGE_HAL_PCIX_533_RESERVED: 2376173139Srwatson default: 2377173139Srwatson rc_status = XGE_HAL_ERR_INVALID_PCI_INFO; 2378173139Srwatson xge_debug_device(XGE_ERR, 2379173139Srwatson "invalid pci info "XGE_OS_LLXFMT, 2380173139Srwatson (unsigned long long)pci_info); 2381173139Srwatson break; 2382173139Srwatson } 2383173139Srwatson if (rc_status != XGE_HAL_ERR_INVALID_PCI_INFO) 2384173139Srwatson xge_debug_device(XGE_TRACE, "PCI info: mode %d width " 2385173139Srwatson "%d frequency %d", *pci_mode, *bus_width, 2386173139Srwatson *bus_frequency); 2387173139Srwatson if (hldev->config.pci_freq_mherz == 2388173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) { 2389173139Srwatson hldev->config.pci_freq_mherz = *bus_frequency; 2390173139Srwatson } 2391171095Ssam } 2392171095Ssam /* for XENA, we report PCI mode, only. PCI bus frequency, and bus width 2393171095Ssam * are set to unknown */ 2394171095Ssam else if (card_id == XGE_HAL_CARD_XENA) { 2395173139Srwatson u32 pcix_status; 2396173139Srwatson u8 dev_num, bus_num; 2397173139Srwatson /* initialize defaults for XENA */ 2398173139Srwatson *bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN; 2399173139Srwatson *bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN; 2400173139Srwatson xge_os_pci_read32(hldev->pdev, hldev->cfgh, 2401173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, pcix_status), 2402173139Srwatson &pcix_status); 2403173139Srwatson dev_num = (u8)((pcix_status & 0xF8) >> 3); 2404173139Srwatson bus_num = (u8)((pcix_status & 0xFF00) >> 8); 2405173139Srwatson if (dev_num == 0 && bus_num == 0) 2406173139Srwatson *pci_mode = XGE_HAL_PCI_BASIC_MODE; 2407173139Srwatson else 2408173139Srwatson *pci_mode = XGE_HAL_PCIX_BASIC_MODE; 2409173139Srwatson xge_debug_device(XGE_TRACE, "PCI info: mode %d", *pci_mode); 2410173139Srwatson if (hldev->config.pci_freq_mherz == 2411173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) { 2412173139Srwatson /* 2413173139Srwatson * There is no way to detect BUS frequency on Xena, 2414173139Srwatson * so, in case of automatic configuration we hopelessly 2415173139Srwatson * assume 133MHZ. 2416173139Srwatson */ 2417173139Srwatson hldev->config.pci_freq_mherz = 2418173139Srwatson XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; 2419173139Srwatson } 2420171095Ssam } else if (card_id == XGE_HAL_CARD_TITAN) { 2421173139Srwatson *bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT; 2422173139Srwatson *bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_250MHZ; 2423173139Srwatson if (hldev->config.pci_freq_mherz == 2424173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) { 2425173139Srwatson hldev->config.pci_freq_mherz = *bus_frequency; 2426173139Srwatson } 2427171095Ssam } else{ 2428173139Srwatson rc_status = XGE_HAL_ERR_BAD_DEVICE_ID; 2429173139Srwatson xge_debug_device(XGE_ERR, "invalid device id %d", card_id); 2430171095Ssam } 2431171095Ssam#endif 2432171095Ssam 2433171095Ssam return rc_status; 2434171095Ssam} 2435171095Ssam 2436171095Ssam/* 2437171095Ssam * __hal_device_handle_link_up_ind 2438171095Ssam * @hldev: HAL device handle. 2439171095Ssam * 2440171095Ssam * Link up indication handler. The function is invoked by HAL when 2441171095Ssam * Xframe indicates that the link is up for programmable amount of time. 2442171095Ssam */ 2443171095Ssamstatic int 2444171095Ssam__hal_device_handle_link_up_ind(xge_hal_device_t *hldev) 2445171095Ssam{ 2446171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2447171095Ssam u64 val64; 2448171095Ssam 2449171095Ssam /* 2450171095Ssam * If the previous link state is not down, return. 2451171095Ssam */ 2452171095Ssam if (hldev->link_state == XGE_HAL_LINK_UP) { 2453171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2454173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){ 2455173139Srwatson val64 = xge_os_pio_mem_read64( 2456173139Srwatson hldev->pdev, hldev->regh0, 2457173139Srwatson &bar0->misc_int_mask); 2458173139Srwatson val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2459173139Srwatson val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2460173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2461173139Srwatson val64, &bar0->misc_int_mask); 2462173139Srwatson } 2463171095Ssam#endif 2464173139Srwatson xge_debug_device(XGE_TRACE, 2465173139Srwatson "link up indication while link is up, ignoring.."); 2466173139Srwatson return 0; 2467171095Ssam } 2468171095Ssam 2469171095Ssam /* Now re-enable it as due to noise, hardware turned it off */ 2470171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2471173139Srwatson &bar0->adapter_control); 2472171095Ssam val64 |= XGE_HAL_ADAPTER_CNTL_EN; 2473171095Ssam val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */ 2474171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2475173139Srwatson &bar0->adapter_control); 2476171095Ssam 2477171095Ssam /* Turn on the Laser */ 2478171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2479173139Srwatson &bar0->adapter_control); 2480171095Ssam val64 = val64|(XGE_HAL_ADAPTER_EOI_TX_ON | 2481173139Srwatson XGE_HAL_ADAPTER_LED_ON); 2482171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2483173139Srwatson &bar0->adapter_control); 2484171095Ssam 2485171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2486171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2487171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2488173139Srwatson &bar0->adapter_status); 2489171095Ssam if (val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2490173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) { 2491173139Srwatson xge_debug_device(XGE_TRACE, "%s", 2492173139Srwatson "fail to transition link to up..."); 2493173139Srwatson return 0; 2494171095Ssam } 2495171095Ssam else { 2496173139Srwatson /* 2497173139Srwatson * Mask the Link Up interrupt and unmask the Link Down 2498173139Srwatson * interrupt. 2499173139Srwatson */ 2500173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2501173139Srwatson &bar0->misc_int_mask); 2502173139Srwatson val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2503173139Srwatson val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2504173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2505173139Srwatson &bar0->misc_int_mask); 2506173139Srwatson xge_debug_device(XGE_TRACE, "calling link up.."); 2507173139Srwatson hldev->link_state = XGE_HAL_LINK_UP; 2508171095Ssam 2509173139Srwatson /* notify ULD */ 2510173139Srwatson if (g_xge_hal_driver->uld_callbacks.link_up) { 2511173139Srwatson g_xge_hal_driver->uld_callbacks.link_up( 2512173139Srwatson hldev->upper_layer_info); 2513173139Srwatson } 2514173139Srwatson return 1; 2515171095Ssam } 2516173139Srwatson } 2517171095Ssam#endif 2518171095Ssam xge_os_mdelay(1); 2519171095Ssam if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0, 2520173139Srwatson (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2521173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT), 2522173139Srwatson XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) { 2523171095Ssam 2524173139Srwatson /* notify ULD */ 2525173139Srwatson (void) xge_queue_produce_context(hldev->queueh, 2526173139Srwatson XGE_HAL_EVENT_LINK_IS_UP, 2527173139Srwatson hldev); 2528173139Srwatson /* link is up after been enabled */ 2529173139Srwatson return 1; 2530171095Ssam } else { 2531173139Srwatson xge_debug_device(XGE_TRACE, "%s", 2532173139Srwatson "fail to transition link to up..."); 2533173139Srwatson return 0; 2534171095Ssam } 2535171095Ssam} 2536171095Ssam 2537171095Ssam/* 2538171095Ssam * __hal_device_handle_link_down_ind 2539171095Ssam * @hldev: HAL device handle. 2540171095Ssam * 2541171095Ssam * Link down indication handler. The function is invoked by HAL when 2542171095Ssam * Xframe indicates that the link is down. 2543171095Ssam */ 2544171095Ssamstatic int 2545171095Ssam__hal_device_handle_link_down_ind(xge_hal_device_t *hldev) 2546171095Ssam{ 2547171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2548171095Ssam u64 val64; 2549171095Ssam 2550171095Ssam /* 2551171095Ssam * If the previous link state is not up, return. 2552171095Ssam */ 2553171095Ssam if (hldev->link_state == XGE_HAL_LINK_DOWN) { 2554173139Srwatson#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2555173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){ 2556173139Srwatson val64 = xge_os_pio_mem_read64( 2557173139Srwatson hldev->pdev, hldev->regh0, 2558173139Srwatson &bar0->misc_int_mask); 2559173139Srwatson val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2560173139Srwatson val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2561173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2562173139Srwatson val64, &bar0->misc_int_mask); 2563173139Srwatson } 2564171095Ssam#endif 2565173139Srwatson xge_debug_device(XGE_TRACE, 2566173139Srwatson "link down indication while link is down, ignoring.."); 2567173139Srwatson return 0; 2568171095Ssam } 2569171095Ssam xge_os_mdelay(1); 2570171095Ssam 2571171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2572173139Srwatson &bar0->adapter_control); 2573171095Ssam 2574171095Ssam /* try to debounce the link only if the adapter is enabled. */ 2575171095Ssam if (val64 & XGE_HAL_ADAPTER_CNTL_EN) { 2576173139Srwatson if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0, 2577173139Srwatson (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2578173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT), 2579173139Srwatson XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) { 2580173139Srwatson xge_debug_device(XGE_TRACE, 2581173139Srwatson "link is actually up (possible noisy link?), ignoring."); 2582173139Srwatson return(0); 2583173139Srwatson } 2584171095Ssam } 2585171095Ssam 2586171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2587173139Srwatson &bar0->adapter_control); 2588171095Ssam /* turn off LED */ 2589171095Ssam val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); 2590171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2591173139Srwatson &bar0->adapter_control); 2592171095Ssam 2593171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2594171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2595173139Srwatson /* 2596173139Srwatson * Mask the Link Down interrupt and unmask the Link up 2597173139Srwatson * interrupt 2598173139Srwatson */ 2599173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2600173139Srwatson &bar0->misc_int_mask); 2601173139Srwatson val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2602173139Srwatson val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2603173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2604173139Srwatson &bar0->misc_int_mask); 2605171095Ssam 2606173139Srwatson /* link is down */ 2607173139Srwatson xge_debug_device(XGE_TRACE, "calling link down.."); 2608173139Srwatson hldev->link_state = XGE_HAL_LINK_DOWN; 2609171095Ssam 2610173139Srwatson /* notify ULD */ 2611173139Srwatson if (g_xge_hal_driver->uld_callbacks.link_down) { 2612173139Srwatson g_xge_hal_driver->uld_callbacks.link_down( 2613173139Srwatson hldev->upper_layer_info); 2614173139Srwatson } 2615173139Srwatson return 1; 2616171095Ssam } 2617171095Ssam#endif 2618171095Ssam /* notify ULD */ 2619171095Ssam (void) xge_queue_produce_context(hldev->queueh, 2620173139Srwatson XGE_HAL_EVENT_LINK_IS_DOWN, 2621173139Srwatson hldev); 2622171095Ssam /* link is down */ 2623171095Ssam return 1; 2624171095Ssam} 2625171095Ssam/* 2626171095Ssam * __hal_device_handle_link_state_change 2627171095Ssam * @hldev: HAL device handle. 2628171095Ssam * 2629171095Ssam * Link state change handler. The function is invoked by HAL when 2630171095Ssam * Xframe indicates link state change condition. The code here makes sure to 2631171095Ssam * 1) ignore redundant state change indications; 2632171095Ssam * 2) execute link-up sequence, and handle the failure to bring the link up; 2633171095Ssam * 3) generate XGE_HAL_LINK_UP/DOWN event for the subsequent handling by 2634171095Ssam * upper-layer driver (ULD). 2635171095Ssam */ 2636171095Ssamstatic int 2637171095Ssam__hal_device_handle_link_state_change(xge_hal_device_t *hldev) 2638171095Ssam{ 2639171095Ssam u64 hw_status; 2640171095Ssam int hw_link_state; 2641171095Ssam int retcode; 2642171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2643171095Ssam u64 val64; 2644171095Ssam int i = 0; 2645171095Ssam 2646171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2647173139Srwatson &bar0->adapter_control); 2648171095Ssam 2649171095Ssam /* If the adapter is not enabled but the hal thinks we are in the up 2650171095Ssam * state then transition to the down state. 2651171095Ssam */ 2652171095Ssam if ( !(val64 & XGE_HAL_ADAPTER_CNTL_EN) && 2653171095Ssam (hldev->link_state == XGE_HAL_LINK_UP) ) { 2654173139Srwatson return(__hal_device_handle_link_down_ind(hldev)); 2655171095Ssam } 2656171095Ssam 2657171095Ssam do { 2658173139Srwatson xge_os_mdelay(1); 2659173139Srwatson (void) xge_hal_device_status(hldev, &hw_status); 2660173139Srwatson hw_link_state = (hw_status & 2661173139Srwatson (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2662173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) ? 2663173139Srwatson XGE_HAL_LINK_DOWN : XGE_HAL_LINK_UP; 2664171095Ssam 2665173139Srwatson /* check if the current link state is still considered 2666173139Srwatson * to be changed. This way we will make sure that this is 2667173139Srwatson * not a noise which needs to be filtered out */ 2668173139Srwatson if (hldev->link_state == hw_link_state) 2669173139Srwatson break; 2670171095Ssam } while (i++ < hldev->config.link_valid_cnt); 2671171095Ssam 2672171095Ssam /* If the current link state is same as previous, just return */ 2673171095Ssam if (hldev->link_state == hw_link_state) 2674173139Srwatson retcode = 0; 2675171095Ssam /* detected state change */ 2676171095Ssam else if (hw_link_state == XGE_HAL_LINK_UP) 2677173139Srwatson retcode = __hal_device_handle_link_up_ind(hldev); 2678171095Ssam else 2679173139Srwatson retcode = __hal_device_handle_link_down_ind(hldev); 2680171095Ssam return retcode; 2681171095Ssam} 2682171095Ssam 2683171095Ssam/* 2684171095Ssam * 2685171095Ssam */ 2686171095Ssamstatic void 2687171095Ssam__hal_device_handle_serr(xge_hal_device_t *hldev, char *reg, u64 value) 2688171095Ssam{ 2689171095Ssam hldev->stats.sw_dev_err_stats.serr_cnt++; 2690171095Ssam if (hldev->config.dump_on_serr) { 2691171095Ssam#ifdef XGE_HAL_USE_MGMT_AUX 2692173139Srwatson (void) xge_hal_aux_device_dump(hldev); 2693171095Ssam#endif 2694171095Ssam } 2695171095Ssam 2696171095Ssam (void) xge_queue_produce(hldev->queueh, XGE_HAL_EVENT_SERR, hldev, 2697173139Srwatson 1, sizeof(u64), (void *)&value); 2698171095Ssam 2699171095Ssam xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, 2700173139Srwatson (unsigned long long) value); 2701171095Ssam} 2702171095Ssam 2703171095Ssam/* 2704171095Ssam * 2705171095Ssam */ 2706171095Ssamstatic void 2707171095Ssam__hal_device_handle_eccerr(xge_hal_device_t *hldev, char *reg, u64 value) 2708171095Ssam{ 2709171095Ssam if (hldev->config.dump_on_eccerr) { 2710171095Ssam#ifdef XGE_HAL_USE_MGMT_AUX 2711173139Srwatson (void) xge_hal_aux_device_dump(hldev); 2712171095Ssam#endif 2713171095Ssam } 2714171095Ssam 2715171095Ssam /* Herc smart enough to recover on its own! */ 2716171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 2717173139Srwatson (void) xge_queue_produce(hldev->queueh, 2718173139Srwatson XGE_HAL_EVENT_ECCERR, hldev, 2719173139Srwatson 1, sizeof(u64), (void *)&value); 2720171095Ssam } 2721171095Ssam 2722173139Srwatson xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, 2723173139Srwatson (unsigned long long) value); 2724171095Ssam} 2725171095Ssam 2726171095Ssam/* 2727171095Ssam * 2728171095Ssam */ 2729171095Ssamstatic void 2730171095Ssam__hal_device_handle_parityerr(xge_hal_device_t *hldev, char *reg, u64 value) 2731171095Ssam{ 2732171095Ssam if (hldev->config.dump_on_parityerr) { 2733171095Ssam#ifdef XGE_HAL_USE_MGMT_AUX 2734173139Srwatson (void) xge_hal_aux_device_dump(hldev); 2735171095Ssam#endif 2736171095Ssam } 2737171095Ssam (void) xge_queue_produce_context(hldev->queueh, 2738173139Srwatson XGE_HAL_EVENT_PARITYERR, hldev); 2739171095Ssam 2740173139Srwatson xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, 2741173139Srwatson (unsigned long long) value); 2742171095Ssam} 2743171095Ssam 2744171095Ssam/* 2745171095Ssam * 2746171095Ssam */ 2747171095Ssamstatic void 2748171095Ssam__hal_device_handle_targetabort(xge_hal_device_t *hldev) 2749171095Ssam{ 2750171095Ssam (void) xge_queue_produce_context(hldev->queueh, 2751173139Srwatson XGE_HAL_EVENT_TARGETABORT, hldev); 2752171095Ssam} 2753171095Ssam 2754171095Ssam 2755171095Ssam/* 2756171095Ssam * __hal_device_hw_initialize 2757171095Ssam * @hldev: HAL device handle. 2758171095Ssam * 2759171095Ssam * Initialize Xframe hardware. 2760171095Ssam */ 2761171095Ssamstatic xge_hal_status_e 2762171095Ssam__hal_device_hw_initialize(xge_hal_device_t *hldev) 2763171095Ssam{ 2764171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2765171095Ssam xge_hal_status_e status; 2766171095Ssam u64 val64; 2767171095Ssam 2768171095Ssam /* Set proper endian settings and verify the same by reading the PIF 2769171095Ssam * Feed-back register. */ 2770171095Ssam status = __hal_device_set_swapper(hldev); 2771171095Ssam if (status != XGE_HAL_OK) { 2772173139Srwatson return status; 2773171095Ssam } 2774171095Ssam 2775171095Ssam /* update the pci mode, frequency, and width */ 2776171095Ssam if (__hal_device_pci_info_get(hldev, &hldev->pci_mode, 2777173139Srwatson &hldev->bus_frequency, &hldev->bus_width) != XGE_HAL_OK){ 2778173139Srwatson hldev->pci_mode = XGE_HAL_PCI_INVALID_MODE; 2779173139Srwatson hldev->bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN; 2780173139Srwatson hldev->bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN; 2781173139Srwatson /* 2782173139Srwatson * FIXME: this cannot happen. 2783173139Srwatson * But if it happens we cannot continue just like that 2784173139Srwatson */ 2785173139Srwatson xge_debug_device(XGE_ERR, "unable to get pci info"); 2786171095Ssam } 2787171095Ssam 2788171095Ssam if ((hldev->pci_mode == XGE_HAL_PCI_33MHZ_MODE) || 2789173139Srwatson (hldev->pci_mode == XGE_HAL_PCI_66MHZ_MODE) || 2790173139Srwatson (hldev->pci_mode == XGE_HAL_PCI_BASIC_MODE)) { 2791173139Srwatson /* PCI optimization: set TxReqTimeOut 2792173139Srwatson * register (0x800+0x120) to 0x1ff or 2793173139Srwatson * something close to this. 2794173139Srwatson * Note: not to be used for PCI-X! */ 2795171095Ssam 2796173139Srwatson val64 = XGE_HAL_TXREQTO_VAL(0x1FF); 2797173139Srwatson val64 |= XGE_HAL_TXREQTO_EN; 2798173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2799173139Srwatson &bar0->txreqtimeout); 2800171095Ssam 2801173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, 2802173139Srwatson &bar0->read_retry_delay); 2803171095Ssam 2804173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, 2805173139Srwatson &bar0->write_retry_delay); 2806171095Ssam 2807173139Srwatson xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI mode"); 2808171095Ssam } 2809171095Ssam 2810171095Ssam if (hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_266MHZ || 2811171095Ssam hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_250MHZ) { 2812171095Ssam 2813173139Srwatson /* Optimizing for PCI-X 266/250 */ 2814171095Ssam 2815173139Srwatson val64 = XGE_HAL_TXREQTO_VAL(0x7F); 2816173139Srwatson val64 |= XGE_HAL_TXREQTO_EN; 2817173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2818173139Srwatson &bar0->txreqtimeout); 2819171095Ssam 2820173139Srwatson xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI-X 266/250 modes"); 2821171095Ssam } 2822171095Ssam 2823171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2824173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL, 2825173139Srwatson &bar0->read_retry_delay); 2826171095Ssam 2827173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL, 2828173139Srwatson &bar0->write_retry_delay); 2829171095Ssam } 2830171095Ssam 2831171095Ssam /* added this to set the no of bytes used to update lso_bytes_sent 2832171095Ssam returned TxD0 */ 2833171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2834173139Srwatson &bar0->pic_control_2); 2835171095Ssam val64 &= ~XGE_HAL_TXD_WRITE_BC(0x2); 2836171095Ssam val64 |= XGE_HAL_TXD_WRITE_BC(0x4); 2837171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2838173139Srwatson &bar0->pic_control_2); 2839171095Ssam /* added this to clear the EOI_RESET field while leaving XGXS_RESET 2840171095Ssam * in reset, then a 1-second delay */ 2841171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2842173139Srwatson XGE_HAL_SW_RESET_XGXS, &bar0->sw_reset); 2843171095Ssam xge_os_mdelay(1000); 2844171095Ssam 2845171095Ssam /* Clear the XGXS_RESET field of the SW_RESET register in order to 2846171095Ssam * release the XGXS from reset. Its reset value is 0xA5; write 0x00 2847171095Ssam * to activate the XGXS. The core requires a minimum 500 us reset.*/ 2848173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0, &bar0->sw_reset); 2849171095Ssam (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2850173139Srwatson &bar0->sw_reset); 2851171095Ssam xge_os_mdelay(1); 2852171095Ssam 2853171095Ssam /* read registers in all blocks */ 2854171095Ssam (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2855173139Srwatson &bar0->mac_int_mask); 2856171095Ssam (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2857173139Srwatson &bar0->mc_int_mask); 2858171095Ssam (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2859173139Srwatson &bar0->xgxs_int_mask); 2860171095Ssam 2861171095Ssam /* set default MTU and steer based on length*/ 2862171095Ssam __hal_ring_mtu_set(hldev, hldev->config.mtu+22); // Alway set 22 bytes extra for steering to work 2863171095Ssam 2864171095Ssam if (hldev->config.mac.rmac_bcast_en) { 2865173139Srwatson xge_hal_device_bcast_enable(hldev); 2866171095Ssam } else { 2867171095Ssam xge_hal_device_bcast_disable(hldev); 2868171095Ssam } 2869171095Ssam 2870171095Ssam#ifndef XGE_HAL_HERC_EMULATION 2871171095Ssam __hal_device_xaui_configure(hldev); 2872171095Ssam#endif 2873171095Ssam __hal_device_mac_link_util_set(hldev); 2874171095Ssam 2875171095Ssam __hal_device_mac_link_util_set(hldev); 2876171095Ssam 2877171095Ssam /* 2878171095Ssam * Keep its PCI REQ# line asserted during a write 2879171095Ssam * transaction up to the end of the transaction 2880171095Ssam */ 2881171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2882173139Srwatson &bar0->misc_control); 2883171095Ssam 2884171095Ssam val64 |= XGE_HAL_MISC_CONTROL_EXT_REQ_EN; 2885171095Ssam 2886171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2887173139Srwatson val64, &bar0->misc_control); 2888171095Ssam 2889171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2890173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2891173139Srwatson &bar0->misc_control); 2892171095Ssam 2893173139Srwatson val64 |= XGE_HAL_MISC_CONTROL_LINK_FAULT; 2894171095Ssam 2895173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2896173139Srwatson val64, &bar0->misc_control); 2897171095Ssam } 2898171095Ssam 2899171095Ssam /* 2900171095Ssam * bimodal interrupts is when all Rx traffic interrupts 2901171095Ssam * will go to TTI, so we need to adjust RTI settings and 2902171095Ssam * use adaptive TTI timer. We need to make sure RTI is 2903171095Ssam * properly configured to sane value which will not 2904171095Ssam * distrupt bimodal behavior. 2905171095Ssam */ 2906171095Ssam if (hldev->config.bimodal_interrupts) { 2907173139Srwatson int i; 2908171095Ssam 2909173139Srwatson /* force polling_cnt to be "0", otherwise 2910173139Srwatson * IRQ workload statistics will be screwed. This could 2911173139Srwatson * be worked out in TXPIC handler later. */ 2912173139Srwatson hldev->config.isr_polling_cnt = 0; 2913173139Srwatson hldev->config.sched_timer_us = 10000; 2914171095Ssam 2915173139Srwatson /* disable all TTI < 56 */ 2916173139Srwatson for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) { 2917173139Srwatson int j; 2918173139Srwatson if (!hldev->config.fifo.queue[i].configured) 2919173139Srwatson continue; 2920173139Srwatson for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) { 2921173139Srwatson if (hldev->config.fifo.queue[i].tti[j].enabled) 2922173139Srwatson hldev->config.fifo.queue[i].tti[j].enabled = 0; 2923173139Srwatson } 2924173139Srwatson } 2925171095Ssam 2926173139Srwatson /* now configure bimodal interrupts */ 2927173139Srwatson __hal_device_bimodal_configure(hldev); 2928171095Ssam } 2929171095Ssam 2930171095Ssam status = __hal_device_tti_configure(hldev, 0); 2931171095Ssam if (status != XGE_HAL_OK) 2932173139Srwatson return status; 2933171095Ssam 2934171095Ssam status = __hal_device_rti_configure(hldev, 0); 2935171095Ssam if (status != XGE_HAL_OK) 2936173139Srwatson return status; 2937171095Ssam 2938171095Ssam status = __hal_device_rth_it_configure(hldev); 2939171095Ssam if (status != XGE_HAL_OK) 2940173139Srwatson return status; 2941171095Ssam 2942171095Ssam status = __hal_device_rth_spdm_configure(hldev); 2943171095Ssam if (status != XGE_HAL_OK) 2944173139Srwatson return status; 2945171095Ssam 2946171095Ssam status = __hal_device_rts_mac_configure(hldev); 2947171095Ssam if (status != XGE_HAL_OK) { 2948173139Srwatson xge_debug_device(XGE_ERR, "__hal_device_rts_mac_configure Failed "); 2949173139Srwatson return status; 2950171095Ssam } 2951171095Ssam 2952171095Ssam status = __hal_device_rts_port_configure(hldev); 2953171095Ssam if (status != XGE_HAL_OK) { 2954173139Srwatson xge_debug_device(XGE_ERR, "__hal_device_rts_port_configure Failed "); 2955173139Srwatson return status; 2956171095Ssam } 2957171095Ssam 2958171095Ssam status = __hal_device_rts_qos_configure(hldev); 2959171095Ssam if (status != XGE_HAL_OK) { 2960173139Srwatson xge_debug_device(XGE_ERR, "__hal_device_rts_qos_configure Failed "); 2961173139Srwatson return status; 2962171095Ssam } 2963171095Ssam 2964171095Ssam __hal_device_pause_frames_configure(hldev); 2965171095Ssam __hal_device_rmac_padding_configure(hldev); 2966171095Ssam __hal_device_shared_splits_configure(hldev); 2967171095Ssam 2968171095Ssam /* make sure all interrupts going to be disabled at the moment */ 2969171095Ssam __hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0); 2970171095Ssam 2971171095Ssam /* SXE-008 Transmit DMA arbitration issue */ 2972171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA && 2973171095Ssam hldev->revision < 4) { 2974173139Srwatson xge_os_pio_mem_write64(hldev->pdev,hldev->regh0, 2975173139Srwatson XGE_HAL_ADAPTER_PCC_ENABLE_FOUR, 2976173139Srwatson &bar0->pcc_enable); 2977171095Ssam } 2978173139Srwatson#if 0 // Removing temporarily as FreeBSD is seeing lower performance 2979173139Srwatson // attributable to this fix. 2980173139Srwatson /* SXE-2-010 */ 2981173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2982173139Srwatson /* Turn off the ECC error reporting for RLDRAM interface */ 2983173139Srwatson if ((status = xge_hal_fix_rldram_ecc_error(hldev)) != XGE_HAL_OK) 2984173139Srwatson return status; 2985173139Srwatson } 2986173139Srwatson#endif 2987171095Ssam __hal_fifo_hw_initialize(hldev); 2988171095Ssam __hal_ring_hw_initialize(hldev); 2989171095Ssam 2990171095Ssam if (__hal_device_wait_quiescent(hldev, &val64)) { 2991173139Srwatson return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 2992171095Ssam } 2993171095Ssam 2994171095Ssam if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1, 2995173139Srwatson XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT, 2996173139Srwatson XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 2997173139Srwatson xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!"); 2998173139Srwatson return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 2999171095Ssam } 3000171095Ssam 3001171095Ssam xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is quiescent", 3002173139Srwatson (unsigned long long)(ulong_t)hldev); 3003171095Ssam 3004171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX || 3005171095Ssam hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI) { 3006173139Srwatson /* 3007173139Srwatson * If MSI is enabled, ensure that One Shot for MSI in PCI_CTRL 3008173139Srwatson * is disabled. 3009173139Srwatson */ 3010173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3011173139Srwatson &bar0->pic_control); 3012173139Srwatson val64 &= ~(XGE_HAL_PIC_CNTL_ONE_SHOT_TINT); 3013173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 3014173139Srwatson &bar0->pic_control); 3015171095Ssam } 3016171095Ssam 3017171095Ssam hldev->hw_is_initialized = 1; 3018171095Ssam hldev->terminating = 0; 3019171095Ssam return XGE_HAL_OK; 3020171095Ssam} 3021171095Ssam 3022171095Ssam/* 3023171095Ssam * __hal_device_reset - Reset device only. 3024171095Ssam * @hldev: HAL device handle. 3025171095Ssam * 3026171095Ssam * Reset the device, and subsequently restore 3027171095Ssam * the previously saved PCI configuration space. 3028171095Ssam */ 3029171095Ssam#define XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT 50 3030171095Ssamstatic xge_hal_status_e 3031171095Ssam__hal_device_reset(xge_hal_device_t *hldev) 3032171095Ssam{ 3033171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 3034171095Ssam int i, j, swap_done, pcisize = 0; 3035171095Ssam u64 val64, rawval = 0ULL; 3036171095Ssam 3037171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 3038173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 3039173139Srwatson if ( hldev->bar2 ) { 3040173139Srwatson u64 *msix_vetor_table = (u64 *)hldev->bar2; 3041171095Ssam 3042173139Srwatson // 2 64bit words for each entry 3043173139Srwatson for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2; 3044173139Srwatson i++) { 3045173139Srwatson hldev->msix_vector_table[i] = 3046173139Srwatson xge_os_pio_mem_read64(hldev->pdev, 3047173139Srwatson hldev->regh2, &msix_vetor_table[i]); 3048173139Srwatson } 3049173139Srwatson } 3050173139Srwatson } 3051171095Ssam } 3052171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3053171095Ssam &bar0->pif_rd_swapper_fb); 3054171095Ssam swap_done = (val64 == XGE_HAL_IF_RD_SWAPPER_FB); 3055171095Ssam 3056171095Ssam if (swap_done) { 3057173139Srwatson __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 3058173139Srwatson (u32)(XGE_HAL_SW_RESET_ALL>>32), (char *)&bar0->sw_reset); 3059171095Ssam } else { 3060173139Srwatson u32 val = (u32)(XGE_HAL_SW_RESET_ALL >> 32); 3061171095Ssam#if defined(XGE_OS_HOST_LITTLE_ENDIAN) || defined(XGE_OS_PIO_LITTLE_ENDIAN) 3062173139Srwatson /* swap it */ 3063173139Srwatson val = (((val & (u32)0x000000ffUL) << 24) | 3064173139Srwatson ((val & (u32)0x0000ff00UL) << 8) | 3065173139Srwatson ((val & (u32)0x00ff0000UL) >> 8) | 3066173139Srwatson ((val & (u32)0xff000000UL) >> 24)); 3067171095Ssam#endif 3068173139Srwatson xge_os_pio_mem_write32(hldev->pdev, hldev->regh0, val, 3069173139Srwatson &bar0->sw_reset); 3070171095Ssam } 3071171095Ssam 3072171095Ssam pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)? 3073173139Srwatson XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA; 3074171095Ssam 3075171095Ssam xge_os_mdelay(20); /* Wait for 20 ms after reset */ 3076171095Ssam 3077171095Ssam { 3078173139Srwatson /* Poll for no more than 1 second */ 3079173139Srwatson for (i = 0; i < XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT; i++) 3080173139Srwatson { 3081173139Srwatson for (j = 0; j < pcisize; j++) { 3082173139Srwatson xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4, 3083173139Srwatson *((u32*)&hldev->pci_config_space + j)); 3084173139Srwatson } 3085171095Ssam 3086173139Srwatson xge_os_pci_read16(hldev->pdev,hldev->cfgh, 3087173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, device_id), 3088173139Srwatson &hldev->device_id); 3089171095Ssam 3090173139Srwatson if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_UNKNOWN) 3091173139Srwatson break; 3092173139Srwatson xge_os_mdelay(20); 3093173139Srwatson } 3094171095Ssam } 3095171095Ssam 3096171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_UNKNOWN) 3097171095Ssam { 3098173139Srwatson xge_debug_device(XGE_ERR, "device reset failed"); 3099173139Srwatson return XGE_HAL_ERR_RESET_FAILED; 3100171095Ssam } 3101171095Ssam 3102171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 3103173139Srwatson int cnt = 0; 3104171095Ssam 3105173139Srwatson rawval = XGE_HAL_SW_RESET_RAW_VAL_HERC; 3106173139Srwatson pcisize = XGE_HAL_PCISIZE_HERC; 3107173139Srwatson xge_os_mdelay(1); 3108173139Srwatson do { 3109173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3110173139Srwatson &bar0->sw_reset); 3111173139Srwatson if (val64 != rawval) { 3112173139Srwatson break; 3113173139Srwatson } 3114173139Srwatson cnt++; 3115173139Srwatson xge_os_mdelay(1); /* Wait for 1ms before retry */ 3116173139Srwatson } while(cnt < 20); 3117171095Ssam } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 3118173139Srwatson rawval = XGE_HAL_SW_RESET_RAW_VAL_XENA; 3119173139Srwatson pcisize = XGE_HAL_PCISIZE_XENA; 3120173139Srwatson xge_os_mdelay(XGE_HAL_DEVICE_RESET_WAIT_MAX_MILLIS); 3121171095Ssam } 3122171095Ssam 3123171095Ssam /* Restore MSI-X vector table */ 3124171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 3125173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 3126173139Srwatson if ( hldev->bar2 ) { 3127173139Srwatson /* 3128173139Srwatson * 94: MSIXTable 00000004 ( BIR:4 Offset:0x0 ) 3129173139Srwatson * 98: PBATable 00000404 ( BIR:4 Offset:0x400 ) 3130173139Srwatson */ 3131173139Srwatson u64 *msix_vetor_table = (u64 *)hldev->bar2; 3132171095Ssam 3133173139Srwatson /* 2 64bit words for each entry */ 3134173139Srwatson for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2; 3135173139Srwatson i++) { 3136173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 3137173139Srwatson hldev->regh2, 3138173139Srwatson hldev->msix_vector_table[i], 3139173139Srwatson &msix_vetor_table[i]); 3140173139Srwatson } 3141173139Srwatson } 3142173139Srwatson } 3143171095Ssam } 3144171095Ssam 3145171095Ssam hldev->link_state = XGE_HAL_LINK_DOWN; 3146171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3147173139Srwatson &bar0->sw_reset); 3148171095Ssam 3149171095Ssam if (val64 != rawval) { 3150173139Srwatson xge_debug_device(XGE_ERR, "device has not been reset " 3151173139Srwatson "got 0x"XGE_OS_LLXFMT", expected 0x"XGE_OS_LLXFMT, 3152173139Srwatson (unsigned long long)val64, (unsigned long long)rawval); 3153171095Ssam return XGE_HAL_ERR_RESET_FAILED; 3154171095Ssam } 3155171095Ssam 3156171095Ssam hldev->hw_is_initialized = 0; 3157171095Ssam return XGE_HAL_OK; 3158171095Ssam} 3159171095Ssam 3160171095Ssam/* 3161171095Ssam * __hal_device_poll - General private routine to poll the device. 3162171095Ssam * @hldev: HAL device handle. 3163171095Ssam * 3164171095Ssam * Returns: one of the xge_hal_status_e{} enumerated types. 3165173139Srwatson * XGE_HAL_OK - for success. 3166171095Ssam * XGE_HAL_ERR_CRITICAL - when encounters critical error. 3167171095Ssam */ 3168171095Ssamstatic xge_hal_status_e 3169171095Ssam__hal_device_poll(xge_hal_device_t *hldev) 3170171095Ssam{ 3171171095Ssam xge_hal_pci_bar0_t *bar0; 3172171095Ssam u64 err_reg; 3173171095Ssam 3174171095Ssam bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 3175171095Ssam 3176171095Ssam /* Handling SERR errors by forcing a H/W reset. */ 3177171095Ssam err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3178173139Srwatson &bar0->serr_source); 3179171095Ssam if (err_reg & XGE_HAL_SERR_SOURCE_ANY) { 3180173139Srwatson __hal_device_handle_serr(hldev, "serr_source", err_reg); 3181173139Srwatson return XGE_HAL_ERR_CRITICAL; 3182171095Ssam } 3183171095Ssam 3184171095Ssam err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3185173139Srwatson &bar0->misc_int_reg); 3186171095Ssam 3187171095Ssam if (err_reg & XGE_HAL_MISC_INT_REG_DP_ERR_INT) { 3188173139Srwatson hldev->stats.sw_dev_err_stats.parity_err_cnt++; 3189173139Srwatson __hal_device_handle_parityerr(hldev, "misc_int_reg", err_reg); 3190173139Srwatson return XGE_HAL_ERR_CRITICAL; 3191171095Ssam } 3192171095Ssam 3193171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 3194171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 3195171095Ssam#endif 3196171095Ssam { 3197171095Ssam 3198173139Srwatson /* Handling link status change error Intr */ 3199173139Srwatson err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3200173139Srwatson &bar0->mac_rmac_err_reg); 3201173139Srwatson if (__hal_device_handle_link_state_change(hldev)) 3202173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3203173139Srwatson err_reg, &bar0->mac_rmac_err_reg); 3204171095Ssam } 3205171095Ssam 3206171095Ssam if (hldev->inject_serr != 0) { 3207173139Srwatson err_reg = hldev->inject_serr; 3208173139Srwatson hldev->inject_serr = 0; 3209173139Srwatson __hal_device_handle_serr(hldev, "inject_serr", err_reg); 3210173139Srwatson return XGE_HAL_ERR_CRITICAL; 3211173139Srwatson } 3212171095Ssam 3213173139Srwatson if (hldev->inject_ecc != 0) { 3214173139Srwatson err_reg = hldev->inject_ecc; 3215173139Srwatson hldev->inject_ecc = 0; 3216173139Srwatson hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 3217173139Srwatson __hal_device_handle_eccerr(hldev, "inject_ecc", err_reg); 3218173139Srwatson return XGE_HAL_ERR_CRITICAL; 3219173139Srwatson } 3220171095Ssam 3221171095Ssam if (hldev->inject_bad_tcode != 0) { 3222173139Srwatson u8 t_code = hldev->inject_bad_tcode; 3223173139Srwatson xge_hal_channel_t channel; 3224173139Srwatson xge_hal_fifo_txd_t txd; 3225173139Srwatson xge_hal_ring_rxd_1_t rxd; 3226171095Ssam 3227173139Srwatson channel.devh = hldev; 3228171095Ssam 3229173139Srwatson if (hldev->inject_bad_tcode_for_chan_type == 3230173139Srwatson XGE_HAL_CHANNEL_TYPE_FIFO) { 3231173139Srwatson channel.type = XGE_HAL_CHANNEL_TYPE_FIFO; 3232171095Ssam 3233173139Srwatson } else { 3234173139Srwatson channel.type = XGE_HAL_CHANNEL_TYPE_RING; 3235173139Srwatson } 3236171095Ssam 3237173139Srwatson hldev->inject_bad_tcode = 0; 3238171095Ssam 3239173139Srwatson if (channel.type == XGE_HAL_CHANNEL_TYPE_FIFO) 3240173139Srwatson return xge_hal_device_handle_tcode(&channel, &txd, 3241173139Srwatson t_code); 3242173139Srwatson else 3243173139Srwatson return xge_hal_device_handle_tcode(&channel, &rxd, 3244173139Srwatson t_code); 3245173139Srwatson } 3246171095Ssam 3247171095Ssam return XGE_HAL_OK; 3248171095Ssam} 3249171095Ssam 3250171095Ssam/* 3251171095Ssam * __hal_verify_pcc_idle - Verify All Enbled PCC are IDLE or not 3252171095Ssam * @hldev: HAL device handle. 3253171095Ssam * @adp_status: Adapter Status value 3254171095Ssam * Usage: See xge_hal_device_enable{}. 3255171095Ssam */ 3256171095Ssamxge_hal_status_e 3257171095Ssam__hal_verify_pcc_idle(xge_hal_device_t *hldev, u64 adp_status) 3258171095Ssam{ 3259171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA && 3260171095Ssam hldev->revision < 4) { 3261173139Srwatson /* 3262173139Srwatson * For Xena 1,2,3 we enable only 4 PCCs Due to 3263173139Srwatson * SXE-008 (Transmit DMA arbitration issue) 3264173139Srwatson */ 3265173139Srwatson if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) 3266173139Srwatson != XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) { 3267173139Srwatson xge_debug_device(XGE_TRACE, "%s", 3268173139Srwatson "PCC is not IDLE after adapter enabled!"); 3269173139Srwatson return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 3270173139Srwatson } 3271171095Ssam } else { 3272173139Srwatson if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) != 3273173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) { 3274173139Srwatson xge_debug_device(XGE_TRACE, "%s", 3275173139Srwatson "PCC is not IDLE after adapter enabled!"); 3276173139Srwatson return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 3277173139Srwatson } 3278171095Ssam } 3279171095Ssam return XGE_HAL_OK; 3280171095Ssam} 3281171095Ssam 3282171095Ssamstatic void 3283171095Ssam__hal_update_bimodal(xge_hal_device_t *hldev, int ring_no) 3284171095Ssam{ 3285171095Ssam int tval, d, iwl_avg, len_avg, bytes_avg, bytes_hist, d_hist; 3286171095Ssam int iwl_rxcnt, iwl_txcnt, iwl_txavg, len_rxavg, iwl_rxavg, len_txavg; 3287171095Ssam int iwl_cnt, i; 3288171095Ssam 3289173139Srwatson#define _HIST_SIZE 50 /* 0.5 sec history */ 3290173139Srwatson#define _HIST_ADJ_TIMER 1 3291173139Srwatson#define _STEP 2 3292171095Ssam 3293171095Ssam static int bytes_avg_history[_HIST_SIZE] = {0}; 3294171095Ssam static int d_avg_history[_HIST_SIZE] = {0}; 3295171095Ssam static int history_idx = 0; 3296171095Ssam static int pstep = 1; 3297171095Ssam static int hist_adj_timer = 0; 3298171095Ssam 3299171095Ssam /* 3300171095Ssam * tval - current value of this bimodal timer 3301171095Ssam */ 3302171095Ssam tval = hldev->bimodal_tti[ring_no].timer_val_us; 3303171095Ssam 3304171095Ssam /* 3305171095Ssam * d - how many interrupts we were getting since last 3306171095Ssam * bimodal timer tick. 3307171095Ssam */ 3308171095Ssam d = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt - 3309173139Srwatson hldev->bimodal_intr_cnt; 3310171095Ssam 3311171095Ssam /* advance bimodal interrupt counter */ 3312171095Ssam hldev->bimodal_intr_cnt = 3313173139Srwatson hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt; 3314171095Ssam 3315171095Ssam /* 3316171095Ssam * iwl_cnt - how many interrupts we've got since last 3317171095Ssam * bimodal timer tick. 3318171095Ssam */ 3319171095Ssam iwl_rxcnt = (hldev->irq_workload_rxcnt[ring_no] ? 3320173139Srwatson hldev->irq_workload_rxcnt[ring_no] : 1); 3321171095Ssam iwl_txcnt = (hldev->irq_workload_txcnt[ring_no] ? 3322173139Srwatson hldev->irq_workload_txcnt[ring_no] : 1); 3323171095Ssam iwl_cnt = iwl_rxcnt + iwl_txcnt; 3324171095Ssam iwl_cnt = iwl_cnt; /* just to remove the lint warning */ 3325171095Ssam 3326171095Ssam /* 3327171095Ssam * we need to take hldev->config.isr_polling_cnt into account 3328171095Ssam * but for some reason this line causing GCC to produce wrong 3329171095Ssam * code on Solaris. As of now, if bimodal_interrupts is configured 3330171095Ssam * hldev->config.isr_polling_cnt is forced to be "0". 3331171095Ssam * 3332171095Ssam * iwl_cnt = iwl_cnt / (hldev->config.isr_polling_cnt + 1); */ 3333171095Ssam 3334171095Ssam /* 3335171095Ssam * iwl_avg - how many RXDs on avarage been processed since 3336171095Ssam * last bimodal timer tick. This indirectly includes 3337171095Ssam * CPU utilizations. 3338171095Ssam */ 3339171095Ssam iwl_rxavg = hldev->irq_workload_rxd[ring_no] / iwl_rxcnt; 3340171095Ssam iwl_txavg = hldev->irq_workload_txd[ring_no] / iwl_txcnt; 3341171095Ssam iwl_avg = iwl_rxavg + iwl_txavg; 3342171095Ssam iwl_avg = iwl_avg == 0 ? 1 : iwl_avg; 3343171095Ssam 3344171095Ssam /* 3345171095Ssam * len_avg - how many bytes on avarage been processed since 3346171095Ssam * last bimodal timer tick. i.e. avarage frame size. 3347171095Ssam */ 3348171095Ssam len_rxavg = 1 + hldev->irq_workload_rxlen[ring_no] / 3349173139Srwatson (hldev->irq_workload_rxd[ring_no] ? 3350173139Srwatson hldev->irq_workload_rxd[ring_no] : 1); 3351171095Ssam len_txavg = 1 + hldev->irq_workload_txlen[ring_no] / 3352173139Srwatson (hldev->irq_workload_txd[ring_no] ? 3353173139Srwatson hldev->irq_workload_txd[ring_no] : 1); 3354171095Ssam len_avg = len_rxavg + len_txavg; 3355171095Ssam if (len_avg < 60) 3356173139Srwatson len_avg = 60; 3357171095Ssam 3358171095Ssam /* align on low boundary */ 3359171095Ssam if ((tval -_STEP) < hldev->config.bimodal_timer_lo_us) 3360173139Srwatson tval = hldev->config.bimodal_timer_lo_us; 3361171095Ssam 3362171095Ssam /* reset faster */ 3363171095Ssam if (iwl_avg == 1) { 3364173139Srwatson tval = hldev->config.bimodal_timer_lo_us; 3365173139Srwatson /* reset history */ 3366173139Srwatson for (i = 0; i < _HIST_SIZE; i++) 3367173139Srwatson bytes_avg_history[i] = d_avg_history[i] = 0; 3368173139Srwatson history_idx = 0; 3369173139Srwatson pstep = 1; 3370173139Srwatson hist_adj_timer = 0; 3371171095Ssam } 3372171095Ssam 3373171095Ssam /* always try to ajust timer to the best throughput value */ 3374171095Ssam bytes_avg = iwl_avg * len_avg; 3375171095Ssam history_idx %= _HIST_SIZE; 3376171095Ssam bytes_avg_history[history_idx] = bytes_avg; 3377171095Ssam d_avg_history[history_idx] = d; 3378171095Ssam history_idx++; 3379171095Ssam d_hist = bytes_hist = 0; 3380171095Ssam for (i = 0; i < _HIST_SIZE; i++) { 3381173139Srwatson /* do not re-configure until history is gathered */ 3382173139Srwatson if (!bytes_avg_history[i]) { 3383173139Srwatson tval = hldev->config.bimodal_timer_lo_us; 3384173139Srwatson goto _end; 3385173139Srwatson } 3386173139Srwatson bytes_hist += bytes_avg_history[i]; 3387173139Srwatson d_hist += d_avg_history[i]; 3388171095Ssam } 3389171095Ssam bytes_hist /= _HIST_SIZE; 3390171095Ssam d_hist /= _HIST_SIZE; 3391171095Ssam 3392173139Srwatson// xge_os_printf("d %d iwl_avg %d len_avg %d:%d:%d tval %d avg %d hist %d pstep %d", 3393173139Srwatson// d, iwl_avg, len_txavg, len_rxavg, len_avg, tval, d*bytes_avg, 3394173139Srwatson// d_hist*bytes_hist, pstep); 3395171095Ssam 3396171095Ssam /* make an adaptive step */ 3397171095Ssam if (d * bytes_avg < d_hist * bytes_hist && hist_adj_timer++ > _HIST_ADJ_TIMER) { 3398173139Srwatson pstep = !pstep; 3399173139Srwatson hist_adj_timer = 0; 3400171095Ssam } 3401171095Ssam 3402171095Ssam if (pstep && 3403171095Ssam (tval + _STEP) <= hldev->config.bimodal_timer_hi_us) { 3404173139Srwatson tval += _STEP; 3405173139Srwatson hldev->stats.sw_dev_info_stats.bimodal_hi_adjust_cnt++; 3406171095Ssam } else if ((tval - _STEP) >= hldev->config.bimodal_timer_lo_us) { 3407173139Srwatson tval -= _STEP; 3408173139Srwatson hldev->stats.sw_dev_info_stats.bimodal_lo_adjust_cnt++; 3409171095Ssam } 3410171095Ssam 3411171095Ssam /* enable TTI range A for better latencies */ 3412171095Ssam hldev->bimodal_urange_a_en = 0; 3413171095Ssam if (tval <= hldev->config.bimodal_timer_lo_us && iwl_avg > 2) 3414173139Srwatson hldev->bimodal_urange_a_en = 1; 3415171095Ssam 3416171095Ssam_end: 3417171095Ssam /* reset workload statistics counters */ 3418171095Ssam hldev->irq_workload_rxcnt[ring_no] = 0; 3419171095Ssam hldev->irq_workload_rxd[ring_no] = 0; 3420171095Ssam hldev->irq_workload_rxlen[ring_no] = 0; 3421171095Ssam hldev->irq_workload_txcnt[ring_no] = 0; 3422171095Ssam hldev->irq_workload_txd[ring_no] = 0; 3423171095Ssam hldev->irq_workload_txlen[ring_no] = 0; 3424171095Ssam 3425171095Ssam /* reconfigure TTI56 + ring_no with new timer value */ 3426171095Ssam hldev->bimodal_timer_val_us = tval; 3427171095Ssam (void) __hal_device_rti_configure(hldev, 1); 3428171095Ssam} 3429171095Ssam 3430171095Ssamstatic void 3431171095Ssam__hal_update_rxufca(xge_hal_device_t *hldev, int ring_no) 3432171095Ssam{ 3433171095Ssam int ufc, ic, i; 3434171095Ssam 3435171095Ssam ufc = hldev->config.ring.queue[ring_no].rti.ufc_a; 3436171095Ssam ic = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt; 3437171095Ssam 3438171095Ssam /* urange_a adaptive coalescing */ 3439171095Ssam if (hldev->rxufca_lbolt > hldev->rxufca_lbolt_time) { 3440173139Srwatson if (ic > hldev->rxufca_intr_thres) { 3441173139Srwatson if (ufc < hldev->config.rxufca_hi_lim) { 3442173139Srwatson ufc += 1; 3443173139Srwatson for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) 3444173139Srwatson hldev->config.ring.queue[i].rti.ufc_a = ufc; 3445173139Srwatson (void) __hal_device_rti_configure(hldev, 1); 3446173139Srwatson hldev->stats.sw_dev_info_stats. 3447173139Srwatson rxufca_hi_adjust_cnt++; 3448173139Srwatson } 3449173139Srwatson hldev->rxufca_intr_thres = ic + 3450173139Srwatson hldev->config.rxufca_intr_thres; /* def: 30 */ 3451173139Srwatson } else { 3452173139Srwatson if (ufc > hldev->config.rxufca_lo_lim) { 3453173139Srwatson ufc -= 1; 3454173139Srwatson for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) 3455173139Srwatson hldev->config.ring.queue[i].rti.ufc_a = ufc; 3456173139Srwatson (void) __hal_device_rti_configure(hldev, 1); 3457173139Srwatson hldev->stats.sw_dev_info_stats. 3458173139Srwatson rxufca_lo_adjust_cnt++; 3459173139Srwatson } 3460173139Srwatson } 3461173139Srwatson hldev->rxufca_lbolt_time = hldev->rxufca_lbolt + 3462173139Srwatson hldev->config.rxufca_lbolt_period; 3463171095Ssam } 3464171095Ssam hldev->rxufca_lbolt++; 3465171095Ssam} 3466171095Ssam 3467171095Ssam/* 3468171095Ssam * __hal_device_handle_mc - Handle MC interrupt reason 3469171095Ssam * @hldev: HAL device handle. 3470171095Ssam * @reason: interrupt reason 3471171095Ssam */ 3472171095Ssamxge_hal_status_e 3473171095Ssam__hal_device_handle_mc(xge_hal_device_t *hldev, u64 reason) 3474171095Ssam{ 3475171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3476171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3477171095Ssam u64 val64; 3478171095Ssam 3479171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3480173139Srwatson &isrbar0->mc_int_status); 3481171095Ssam if (!(val64 & XGE_HAL_MC_INT_STATUS_MC_INT)) 3482173139Srwatson return XGE_HAL_OK; 3483171095Ssam 3484171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3485173139Srwatson &isrbar0->mc_err_reg); 3486171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3487173139Srwatson val64, &isrbar0->mc_err_reg); 3488171095Ssam 3489171095Ssam if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_L || 3490171095Ssam val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_U || 3491171095Ssam val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_0 || 3492171095Ssam val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_1 || 3493171095Ssam (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA && 3494171095Ssam (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_L || 3495171095Ssam val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_U || 3496171095Ssam val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_L || 3497171095Ssam val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_U))) { 3498173139Srwatson hldev->stats.sw_dev_err_stats.single_ecc_err_cnt++; 3499173139Srwatson hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 3500171095Ssam } 3501171095Ssam 3502171095Ssam if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_L || 3503171095Ssam val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_U || 3504171095Ssam val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 || 3505171095Ssam val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1 || 3506171095Ssam (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA && 3507171095Ssam (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_L || 3508171095Ssam val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_U || 3509171095Ssam val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_L || 3510171095Ssam val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_U))) { 3511173139Srwatson hldev->stats.sw_dev_err_stats.double_ecc_err_cnt++; 3512173139Srwatson hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 3513171095Ssam } 3514171095Ssam 3515171095Ssam if (val64 & XGE_HAL_MC_ERR_REG_SM_ERR) { 3516173139Srwatson hldev->stats.sw_dev_err_stats.sm_err_cnt++; 3517171095Ssam } 3518171095Ssam 3519171095Ssam /* those two should result in device reset */ 3520171095Ssam if (val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 || 3521171095Ssam val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1) { 3522173139Srwatson __hal_device_handle_eccerr(hldev, "mc_err_reg", val64); 3523173139Srwatson return XGE_HAL_ERR_CRITICAL; 3524171095Ssam } 3525171095Ssam 3526171095Ssam return XGE_HAL_OK; 3527171095Ssam} 3528171095Ssam 3529171095Ssam/* 3530171095Ssam * __hal_device_handle_pic - Handle non-traffic PIC interrupt reason 3531171095Ssam * @hldev: HAL device handle. 3532171095Ssam * @reason: interrupt reason 3533171095Ssam */ 3534171095Ssamxge_hal_status_e 3535171095Ssam__hal_device_handle_pic(xge_hal_device_t *hldev, u64 reason) 3536171095Ssam{ 3537171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3538171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3539171095Ssam u64 val64; 3540171095Ssam 3541171095Ssam if (reason & XGE_HAL_PIC_INT_FLSH) { 3542173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3543173139Srwatson &isrbar0->flsh_int_reg); 3544173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3545173139Srwatson val64, &isrbar0->flsh_int_reg); 3546173139Srwatson /* FIXME: handle register */ 3547171095Ssam } 3548171095Ssam if (reason & XGE_HAL_PIC_INT_MDIO) { 3549173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3550173139Srwatson &isrbar0->mdio_int_reg); 3551173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3552173139Srwatson val64, &isrbar0->mdio_int_reg); 3553173139Srwatson /* FIXME: handle register */ 3554171095Ssam } 3555171095Ssam if (reason & XGE_HAL_PIC_INT_IIC) { 3556173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3557173139Srwatson &isrbar0->iic_int_reg); 3558173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3559173139Srwatson val64, &isrbar0->iic_int_reg); 3560173139Srwatson /* FIXME: handle register */ 3561171095Ssam } 3562171095Ssam if (reason & XGE_HAL_PIC_INT_MISC) { 3563173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, 3564173139Srwatson hldev->regh0, &isrbar0->misc_int_reg); 3565171095Ssam#ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 3566173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 3567173139Srwatson /* Check for Link interrupts. If both Link Up/Down 3568173139Srwatson * bits are set, clear both and check adapter status 3569173139Srwatson */ 3570173139Srwatson if ((val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) && 3571173139Srwatson (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT)) { 3572173139Srwatson u64 temp64; 3573171095Ssam 3574173139Srwatson xge_debug_device(XGE_TRACE, 3575173139Srwatson "both link up and link down detected "XGE_OS_LLXFMT, 3576173139Srwatson (unsigned long long)val64); 3577171095Ssam 3578173139Srwatson temp64 = (XGE_HAL_MISC_INT_REG_LINK_DOWN_INT | 3579173139Srwatson XGE_HAL_MISC_INT_REG_LINK_UP_INT); 3580173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 3581173139Srwatson hldev->regh0, temp64, 3582173139Srwatson &isrbar0->misc_int_reg); 3583173139Srwatson } 3584173139Srwatson else if (val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) { 3585173139Srwatson xge_debug_device(XGE_TRACE, 3586173139Srwatson "link up call request, misc_int "XGE_OS_LLXFMT, 3587173139Srwatson (unsigned long long)val64); 3588173139Srwatson __hal_device_handle_link_up_ind(hldev); 3589173139Srwatson } 3590173139Srwatson else if (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT){ 3591173139Srwatson xge_debug_device(XGE_TRACE, 3592173139Srwatson "link down request, misc_int "XGE_OS_LLXFMT, 3593173139Srwatson (unsigned long long)val64); 3594173139Srwatson __hal_device_handle_link_down_ind(hldev); 3595173139Srwatson } 3596173139Srwatson } else 3597171095Ssam#endif 3598173139Srwatson { 3599173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3600173139Srwatson val64, &isrbar0->misc_int_reg); 3601173139Srwatson } 3602171095Ssam } 3603171095Ssam 3604171095Ssam return XGE_HAL_OK; 3605171095Ssam} 3606171095Ssam 3607171095Ssam/* 3608171095Ssam * __hal_device_handle_txpic - Handle TxPIC interrupt reason 3609171095Ssam * @hldev: HAL device handle. 3610171095Ssam * @reason: interrupt reason 3611171095Ssam */ 3612171095Ssamxge_hal_status_e 3613171095Ssam__hal_device_handle_txpic(xge_hal_device_t *hldev, u64 reason) 3614171095Ssam{ 3615171095Ssam xge_hal_status_e status = XGE_HAL_OK; 3616171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3617171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3618171095Ssam volatile u64 val64; 3619171095Ssam 3620171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3621173139Srwatson &isrbar0->pic_int_status); 3622171095Ssam if ( val64 & (XGE_HAL_PIC_INT_FLSH | 3623173139Srwatson XGE_HAL_PIC_INT_MDIO | 3624173139Srwatson XGE_HAL_PIC_INT_IIC | 3625173139Srwatson XGE_HAL_PIC_INT_MISC) ) { 3626173139Srwatson status = __hal_device_handle_pic(hldev, val64); 3627173139Srwatson xge_os_wmb(); 3628171095Ssam } 3629171095Ssam 3630171095Ssam if (!(val64 & XGE_HAL_PIC_INT_TX)) 3631173139Srwatson return status; 3632171095Ssam 3633171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3634173139Srwatson &isrbar0->txpic_int_reg); 3635171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3636173139Srwatson val64, &isrbar0->txpic_int_reg); 3637171095Ssam xge_os_wmb(); 3638171095Ssam 3639171095Ssam if (val64 & XGE_HAL_TXPIC_INT_SCHED_INTR) { 3640173139Srwatson int i; 3641171095Ssam 3642173139Srwatson if (g_xge_hal_driver->uld_callbacks.sched_timer != NULL) 3643173139Srwatson g_xge_hal_driver->uld_callbacks.sched_timer( 3644173139Srwatson hldev, hldev->upper_layer_info); 3645173139Srwatson /* 3646173139Srwatson * This feature implements adaptive receive interrupt 3647173139Srwatson * coalecing. It is disabled by default. To enable it 3648173139Srwatson * set hldev->config.rxufca_lo_lim to be not equal to 3649173139Srwatson * hldev->config.rxufca_hi_lim. 3650173139Srwatson * 3651173139Srwatson * We are using HW timer for this feature, so 3652173139Srwatson * use needs to configure hldev->config.rxufca_lbolt_period 3653173139Srwatson * which is essentially a time slice of timer. 3654173139Srwatson * 3655173139Srwatson * For those who familiar with Linux, lbolt means jiffies 3656173139Srwatson * of this timer. I.e. timer tick. 3657173139Srwatson */ 3658173139Srwatson if (hldev->config.rxufca_lo_lim != 3659173139Srwatson hldev->config.rxufca_hi_lim && 3660173139Srwatson hldev->config.rxufca_lo_lim != 0) { 3661173139Srwatson for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 3662173139Srwatson if (!hldev->config.ring.queue[i].configured) 3663173139Srwatson continue; 3664173139Srwatson if (hldev->config.ring.queue[i].rti.urange_a) 3665173139Srwatson __hal_update_rxufca(hldev, i); 3666173139Srwatson } 3667173139Srwatson } 3668171095Ssam 3669173139Srwatson /* 3670173139Srwatson * This feature implements adaptive TTI timer re-calculation 3671173139Srwatson * based on host utilization, number of interrupt processed, 3672173139Srwatson * number of RXD per tick and avarage length of packets per 3673173139Srwatson * tick. 3674173139Srwatson */ 3675173139Srwatson if (hldev->config.bimodal_interrupts) { 3676173139Srwatson for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 3677173139Srwatson if (!hldev->config.ring.queue[i].configured) 3678173139Srwatson continue; 3679173139Srwatson if (hldev->bimodal_tti[i].enabled) 3680173139Srwatson __hal_update_bimodal(hldev, i); 3681173139Srwatson } 3682173139Srwatson } 3683171095Ssam } 3684171095Ssam 3685171095Ssam return XGE_HAL_OK; 3686171095Ssam} 3687171095Ssam 3688171095Ssam/* 3689171095Ssam * __hal_device_handle_txdma - Handle TxDMA interrupt reason 3690171095Ssam * @hldev: HAL device handle. 3691171095Ssam * @reason: interrupt reason 3692171095Ssam */ 3693171095Ssamxge_hal_status_e 3694171095Ssam__hal_device_handle_txdma(xge_hal_device_t *hldev, u64 reason) 3695171095Ssam{ 3696171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3697171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3698171095Ssam u64 val64, temp64, err; 3699171095Ssam 3700171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3701173139Srwatson &isrbar0->txdma_int_status); 3702171095Ssam if (val64 & XGE_HAL_TXDMA_PFC_INT) { 3703173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3704173139Srwatson &isrbar0->pfc_err_reg); 3705173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3706173139Srwatson err, &isrbar0->pfc_err_reg); 3707173139Srwatson hldev->stats.sw_dev_info_stats.pfc_err_cnt++; 3708173139Srwatson temp64 = XGE_HAL_PFC_ECC_DB_ERR|XGE_HAL_PFC_SM_ERR_ALARM 3709173139Srwatson |XGE_HAL_PFC_MISC_0_ERR|XGE_HAL_PFC_MISC_1_ERR 3710173139Srwatson |XGE_HAL_PFC_PCIX_ERR; 3711173139Srwatson if (val64 & temp64) 3712173139Srwatson goto reset; 3713171095Ssam } 3714171095Ssam if (val64 & XGE_HAL_TXDMA_TDA_INT) { 3715173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3716173139Srwatson &isrbar0->tda_err_reg); 3717173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3718173139Srwatson err, &isrbar0->tda_err_reg); 3719173139Srwatson hldev->stats.sw_dev_info_stats.tda_err_cnt++; 3720173139Srwatson temp64 = XGE_HAL_TDA_Fn_ECC_DB_ERR|XGE_HAL_TDA_SM0_ERR_ALARM 3721173139Srwatson |XGE_HAL_TDA_SM1_ERR_ALARM; 3722173139Srwatson if (val64 & temp64) 3723173139Srwatson goto reset; 3724171095Ssam } 3725171095Ssam if (val64 & XGE_HAL_TXDMA_PCC_INT) { 3726173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3727173139Srwatson &isrbar0->pcc_err_reg); 3728173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3729173139Srwatson err, &isrbar0->pcc_err_reg); 3730173139Srwatson hldev->stats.sw_dev_info_stats.pcc_err_cnt++; 3731173139Srwatson temp64 = XGE_HAL_PCC_FB_ECC_DB_ERR|XGE_HAL_PCC_TXB_ECC_DB_ERR 3732173139Srwatson |XGE_HAL_PCC_SM_ERR_ALARM|XGE_HAL_PCC_WR_ERR_ALARM 3733173139Srwatson |XGE_HAL_PCC_N_SERR|XGE_HAL_PCC_6_COF_OV_ERR 3734173139Srwatson |XGE_HAL_PCC_7_COF_OV_ERR|XGE_HAL_PCC_6_LSO_OV_ERR 3735173139Srwatson |XGE_HAL_PCC_7_LSO_OV_ERR; 3736173139Srwatson if (val64 & temp64) 3737173139Srwatson goto reset; 3738171095Ssam } 3739171095Ssam if (val64 & XGE_HAL_TXDMA_TTI_INT) { 3740173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3741173139Srwatson &isrbar0->tti_err_reg); 3742173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3743173139Srwatson err, &isrbar0->tti_err_reg); 3744173139Srwatson hldev->stats.sw_dev_info_stats.tti_err_cnt++; 3745173139Srwatson temp64 = XGE_HAL_TTI_SM_ERR_ALARM; 3746173139Srwatson if (val64 & temp64) 3747173139Srwatson goto reset; 3748171095Ssam } 3749171095Ssam if (val64 & XGE_HAL_TXDMA_LSO_INT) { 3750173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3751173139Srwatson &isrbar0->lso_err_reg); 3752173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3753173139Srwatson err, &isrbar0->lso_err_reg); 3754173139Srwatson hldev->stats.sw_dev_info_stats.lso_err_cnt++; 3755173139Srwatson temp64 = XGE_HAL_LSO6_ABORT|XGE_HAL_LSO7_ABORT 3756173139Srwatson |XGE_HAL_LSO6_SM_ERR_ALARM|XGE_HAL_LSO7_SM_ERR_ALARM; 3757173139Srwatson if (val64 & temp64) 3758173139Srwatson goto reset; 3759171095Ssam } 3760171095Ssam if (val64 & XGE_HAL_TXDMA_TPA_INT) { 3761173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3762173139Srwatson &isrbar0->tpa_err_reg); 3763173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3764173139Srwatson err, &isrbar0->tpa_err_reg); 3765173139Srwatson hldev->stats.sw_dev_info_stats.tpa_err_cnt++; 3766173139Srwatson temp64 = XGE_HAL_TPA_SM_ERR_ALARM; 3767173139Srwatson if (val64 & temp64) 3768173139Srwatson goto reset; 3769171095Ssam } 3770171095Ssam if (val64 & XGE_HAL_TXDMA_SM_INT) { 3771173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3772173139Srwatson &isrbar0->sm_err_reg); 3773173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3774173139Srwatson err, &isrbar0->sm_err_reg); 3775173139Srwatson hldev->stats.sw_dev_info_stats.sm_err_cnt++; 3776173139Srwatson temp64 = XGE_HAL_SM_SM_ERR_ALARM; 3777173139Srwatson if (val64 & temp64) 3778173139Srwatson goto reset; 3779171095Ssam } 3780171095Ssam 3781171095Ssam return XGE_HAL_OK; 3782171095Ssam 3783171095Ssamreset : xge_hal_device_reset(hldev); 3784171095Ssam xge_hal_device_enable(hldev); 3785171095Ssam xge_hal_device_intr_enable(hldev); 3786171095Ssam return XGE_HAL_OK; 3787171095Ssam} 3788171095Ssam 3789171095Ssam/* 3790171095Ssam * __hal_device_handle_txmac - Handle TxMAC interrupt reason 3791171095Ssam * @hldev: HAL device handle. 3792171095Ssam * @reason: interrupt reason 3793171095Ssam */ 3794171095Ssamxge_hal_status_e 3795171095Ssam__hal_device_handle_txmac(xge_hal_device_t *hldev, u64 reason) 3796171095Ssam{ 3797171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3798171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3799171095Ssam u64 val64, temp64; 3800171095Ssam 3801171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3802173139Srwatson &isrbar0->mac_int_status); 3803171095Ssam if (!(val64 & XGE_HAL_MAC_INT_STATUS_TMAC_INT)) 3804173139Srwatson return XGE_HAL_OK; 3805171095Ssam 3806171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3807173139Srwatson &isrbar0->mac_tmac_err_reg); 3808171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3809173139Srwatson val64, &isrbar0->mac_tmac_err_reg); 3810171095Ssam hldev->stats.sw_dev_info_stats.mac_tmac_err_cnt++; 3811171095Ssam temp64 = XGE_HAL_TMAC_TX_BUF_OVRN|XGE_HAL_TMAC_TX_SM_ERR; 3812171095Ssam if (val64 & temp64) { 3813173139Srwatson xge_hal_device_reset(hldev); 3814173139Srwatson xge_hal_device_enable(hldev); 3815173139Srwatson xge_hal_device_intr_enable(hldev); 3816171095Ssam } 3817171095Ssam 3818171095Ssam return XGE_HAL_OK; 3819171095Ssam} 3820171095Ssam 3821171095Ssam/* 3822171095Ssam * __hal_device_handle_txxgxs - Handle TxXGXS interrupt reason 3823171095Ssam * @hldev: HAL device handle. 3824171095Ssam * @reason: interrupt reason 3825171095Ssam */ 3826171095Ssamxge_hal_status_e 3827171095Ssam__hal_device_handle_txxgxs(xge_hal_device_t *hldev, u64 reason) 3828171095Ssam{ 3829171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3830171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3831171095Ssam u64 val64, temp64; 3832171095Ssam 3833171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3834173139Srwatson &isrbar0->xgxs_int_status); 3835171095Ssam if (!(val64 & XGE_HAL_XGXS_INT_STATUS_TXGXS)) 3836173139Srwatson return XGE_HAL_OK; 3837171095Ssam 3838171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3839173139Srwatson &isrbar0->xgxs_txgxs_err_reg); 3840171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3841173139Srwatson val64, &isrbar0->xgxs_txgxs_err_reg); 3842171095Ssam hldev->stats.sw_dev_info_stats.xgxs_txgxs_err_cnt++; 3843171095Ssam temp64 = XGE_HAL_TXGXS_ESTORE_UFLOW|XGE_HAL_TXGXS_TX_SM_ERR; 3844171095Ssam if (val64 & temp64) { 3845173139Srwatson xge_hal_device_reset(hldev); 3846173139Srwatson xge_hal_device_enable(hldev); 3847173139Srwatson xge_hal_device_intr_enable(hldev); 3848171095Ssam } 3849171095Ssam 3850171095Ssam return XGE_HAL_OK; 3851171095Ssam} 3852171095Ssam 3853171095Ssam/* 3854171095Ssam * __hal_device_handle_rxpic - Handle RxPIC interrupt reason 3855171095Ssam * @hldev: HAL device handle. 3856171095Ssam * @reason: interrupt reason 3857171095Ssam */ 3858171095Ssamxge_hal_status_e 3859171095Ssam__hal_device_handle_rxpic(xge_hal_device_t *hldev, u64 reason) 3860171095Ssam{ 3861171095Ssam /* FIXME: handle register */ 3862171095Ssam 3863171095Ssam return XGE_HAL_OK; 3864171095Ssam} 3865171095Ssam 3866171095Ssam/* 3867171095Ssam * __hal_device_handle_rxdma - Handle RxDMA interrupt reason 3868171095Ssam * @hldev: HAL device handle. 3869171095Ssam * @reason: interrupt reason 3870171095Ssam */ 3871171095Ssamxge_hal_status_e 3872171095Ssam__hal_device_handle_rxdma(xge_hal_device_t *hldev, u64 reason) 3873171095Ssam{ 3874171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3875171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3876171095Ssam u64 val64, err, temp64; 3877171095Ssam 3878171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3879173139Srwatson &isrbar0->rxdma_int_status); 3880171095Ssam if (val64 & XGE_HAL_RXDMA_RC_INT) { 3881173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3882173139Srwatson &isrbar0->rc_err_reg); 3883173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3884173139Srwatson err, &isrbar0->rc_err_reg); 3885173139Srwatson hldev->stats.sw_dev_info_stats.rc_err_cnt++; 3886173139Srwatson temp64 = XGE_HAL_RC_PRCn_ECC_DB_ERR|XGE_HAL_RC_FTC_ECC_DB_ERR 3887173139Srwatson |XGE_HAL_RC_PRCn_SM_ERR_ALARM 3888173139Srwatson |XGE_HAL_RC_FTC_SM_ERR_ALARM; 3889173139Srwatson if (val64 & temp64) 3890173139Srwatson goto reset; 3891171095Ssam } 3892171095Ssam if (val64 & XGE_HAL_RXDMA_RPA_INT) { 3893173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3894173139Srwatson &isrbar0->rpa_err_reg); 3895173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3896173139Srwatson err, &isrbar0->rpa_err_reg); 3897173139Srwatson hldev->stats.sw_dev_info_stats.rpa_err_cnt++; 3898173139Srwatson temp64 = XGE_HAL_RPA_SM_ERR_ALARM|XGE_HAL_RPA_CREDIT_ERR; 3899173139Srwatson if (val64 & temp64) 3900173139Srwatson goto reset; 3901171095Ssam } 3902171095Ssam if (val64 & XGE_HAL_RXDMA_RDA_INT) { 3903173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3904173139Srwatson &isrbar0->rda_err_reg); 3905173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3906173139Srwatson err, &isrbar0->rda_err_reg); 3907173139Srwatson hldev->stats.sw_dev_info_stats.rda_err_cnt++; 3908173139Srwatson temp64 = XGE_HAL_RDA_RXDn_ECC_DB_ERR 3909173139Srwatson |XGE_HAL_RDA_FRM_ECC_DB_N_AERR 3910173139Srwatson |XGE_HAL_RDA_SM1_ERR_ALARM|XGE_HAL_RDA_SM0_ERR_ALARM 3911173139Srwatson |XGE_HAL_RDA_RXD_ECC_DB_SERR; 3912173139Srwatson if (val64 & temp64) 3913173139Srwatson goto reset; 3914171095Ssam } 3915171095Ssam if (val64 & XGE_HAL_RXDMA_RTI_INT) { 3916173139Srwatson err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3917173139Srwatson &isrbar0->rti_err_reg); 3918173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3919173139Srwatson err, &isrbar0->rti_err_reg); 3920173139Srwatson hldev->stats.sw_dev_info_stats.rti_err_cnt++; 3921173139Srwatson temp64 = XGE_HAL_RTI_SM_ERR_ALARM; 3922173139Srwatson if (val64 & temp64) 3923173139Srwatson goto reset; 3924171095Ssam } 3925171095Ssam 3926171095Ssam return XGE_HAL_OK; 3927171095Ssam 3928171095Ssamreset : xge_hal_device_reset(hldev); 3929171095Ssam xge_hal_device_enable(hldev); 3930171095Ssam xge_hal_device_intr_enable(hldev); 3931171095Ssam return XGE_HAL_OK; 3932171095Ssam} 3933171095Ssam 3934171095Ssam/* 3935171095Ssam * __hal_device_handle_rxmac - Handle RxMAC interrupt reason 3936171095Ssam * @hldev: HAL device handle. 3937171095Ssam * @reason: interrupt reason 3938171095Ssam */ 3939171095Ssamxge_hal_status_e 3940171095Ssam__hal_device_handle_rxmac(xge_hal_device_t *hldev, u64 reason) 3941171095Ssam{ 3942171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3943171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3944171095Ssam u64 val64, temp64; 3945171095Ssam 3946171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3947173139Srwatson &isrbar0->mac_int_status); 3948171095Ssam if (!(val64 & XGE_HAL_MAC_INT_STATUS_RMAC_INT)) 3949173139Srwatson return XGE_HAL_OK; 3950171095Ssam 3951171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3952173139Srwatson &isrbar0->mac_rmac_err_reg); 3953171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3954173139Srwatson val64, &isrbar0->mac_rmac_err_reg); 3955171095Ssam hldev->stats.sw_dev_info_stats.mac_rmac_err_cnt++; 3956171095Ssam temp64 = XGE_HAL_RMAC_RX_BUFF_OVRN|XGE_HAL_RMAC_RX_SM_ERR; 3957171095Ssam if (val64 & temp64) { 3958173139Srwatson xge_hal_device_reset(hldev); 3959173139Srwatson xge_hal_device_enable(hldev); 3960173139Srwatson xge_hal_device_intr_enable(hldev); 3961171095Ssam } 3962171095Ssam 3963171095Ssam return XGE_HAL_OK; 3964171095Ssam} 3965171095Ssam 3966171095Ssam/* 3967171095Ssam * __hal_device_handle_rxxgxs - Handle RxXGXS interrupt reason 3968171095Ssam * @hldev: HAL device handle. 3969171095Ssam * @reason: interrupt reason 3970171095Ssam */ 3971171095Ssamxge_hal_status_e 3972171095Ssam__hal_device_handle_rxxgxs(xge_hal_device_t *hldev, u64 reason) 3973171095Ssam{ 3974171095Ssam xge_hal_pci_bar0_t *isrbar0 = 3975171095Ssam (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3976171095Ssam u64 val64, temp64; 3977171095Ssam 3978171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3979173139Srwatson &isrbar0->xgxs_int_status); 3980171095Ssam if (!(val64 & XGE_HAL_XGXS_INT_STATUS_RXGXS)) 3981173139Srwatson return XGE_HAL_OK; 3982171095Ssam 3983171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3984173139Srwatson &isrbar0->xgxs_rxgxs_err_reg); 3985171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3986173139Srwatson val64, &isrbar0->xgxs_rxgxs_err_reg); 3987171095Ssam hldev->stats.sw_dev_info_stats.xgxs_rxgxs_err_cnt++; 3988171095Ssam temp64 = XGE_HAL_RXGXS_ESTORE_OFLOW|XGE_HAL_RXGXS_RX_SM_ERR; 3989171095Ssam if (val64 & temp64) { 3990173139Srwatson xge_hal_device_reset(hldev); 3991173139Srwatson xge_hal_device_enable(hldev); 3992173139Srwatson xge_hal_device_intr_enable(hldev); 3993171095Ssam } 3994171095Ssam 3995171095Ssam return XGE_HAL_OK; 3996171095Ssam} 3997171095Ssam 3998171095Ssam/** 3999171095Ssam * xge_hal_device_enable - Enable device. 4000171095Ssam * @hldev: HAL device handle. 4001171095Ssam * 4002171095Ssam * Enable the specified device: bring up the link/interface. 4003171095Ssam * Returns: XGE_HAL_OK - success. 4004171095Ssam * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device 4005171095Ssam * to a "quiescent" state. 4006171095Ssam * 4007171095Ssam * See also: xge_hal_status_e{}. 4008171095Ssam * 4009171095Ssam * Usage: See ex_open{}. 4010171095Ssam */ 4011171095Ssamxge_hal_status_e 4012171095Ssamxge_hal_device_enable(xge_hal_device_t *hldev) 4013171095Ssam{ 4014171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4015171095Ssam u64 val64; 4016171095Ssam u64 adp_status; 4017171095Ssam int i, j; 4018171095Ssam 4019171095Ssam if (!hldev->hw_is_initialized) { 4020173139Srwatson xge_hal_status_e status; 4021171095Ssam 4022173139Srwatson status = __hal_device_hw_initialize(hldev); 4023173139Srwatson if (status != XGE_HAL_OK) { 4024173139Srwatson return status; 4025173139Srwatson } 4026171095Ssam } 4027171095Ssam 4028171095Ssam /* 4029171095Ssam * Not needed in most cases, i.e. 4030171095Ssam * when device_disable() is followed by reset - 4031171095Ssam * the latter copies back PCI config space, along with 4032171095Ssam * the bus mastership - see __hal_device_reset(). 4033171095Ssam * However, there are/may-in-future be other cases, and 4034171095Ssam * does not hurt. 4035171095Ssam */ 4036171095Ssam __hal_device_bus_master_enable(hldev); 4037171095Ssam 4038171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 4039173139Srwatson /* 4040173139Srwatson * Configure the link stability period. 4041173139Srwatson */ 4042173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4043173139Srwatson &bar0->misc_control); 4044173139Srwatson if (hldev->config.link_stability_period != 4045173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) { 4046171095Ssam 4047173139Srwatson val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD( 4048173139Srwatson hldev->config.link_stability_period); 4049173139Srwatson } else { 4050173139Srwatson /* 4051173139Srwatson * Use the link stability period 1 ms as default 4052173139Srwatson */ 4053173139Srwatson val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD( 4054173139Srwatson XGE_HAL_DEFAULT_LINK_STABILITY_PERIOD); 4055173139Srwatson } 4056173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4057173139Srwatson val64, &bar0->misc_control); 4058171095Ssam 4059173139Srwatson /* 4060173139Srwatson * Clearing any possible Link up/down interrupts that 4061173139Srwatson * could have popped up just before Enabling the card. 4062173139Srwatson */ 4063173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4064173139Srwatson &bar0->misc_int_reg); 4065173139Srwatson if (val64) { 4066173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4067173139Srwatson val64, &bar0->misc_int_reg); 4068173139Srwatson xge_debug_device(XGE_TRACE, "%s","link state cleared"); 4069173139Srwatson } 4070171095Ssam } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 4071173139Srwatson /* 4072173139Srwatson * Clearing any possible Link state change interrupts that 4073173139Srwatson * could have popped up just before Enabling the card. 4074173139Srwatson */ 4075173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4076173139Srwatson &bar0->mac_rmac_err_reg); 4077173139Srwatson if (val64) { 4078173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4079173139Srwatson val64, &bar0->mac_rmac_err_reg); 4080173139Srwatson xge_debug_device(XGE_TRACE, "%s", "link state cleared"); 4081173139Srwatson } 4082171095Ssam } 4083171095Ssam 4084171095Ssam if (__hal_device_wait_quiescent(hldev, &val64)) { 4085173139Srwatson return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4086171095Ssam } 4087171095Ssam 4088171095Ssam /* Enabling Laser. */ 4089171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4090173139Srwatson &bar0->adapter_control); 4091171095Ssam val64 |= XGE_HAL_ADAPTER_EOI_TX_ON; 4092171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4093171095Ssam &bar0->adapter_control); 4094171095Ssam 4095171095Ssam /* let link establish */ 4096171095Ssam xge_os_mdelay(1); 4097171095Ssam 4098171095Ssam /* set link down untill poll() routine will set it up (maybe) */ 4099171095Ssam hldev->link_state = XGE_HAL_LINK_DOWN; 4100171095Ssam 4101171095Ssam /* If link is UP (adpter is connected) then enable the adapter */ 4102171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4103171095Ssam &bar0->adapter_status); 4104171095Ssam if( val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 4105173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT) ) { 4106173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4107173139Srwatson &bar0->adapter_control); 4108173139Srwatson val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); 4109171095Ssam } else { 4110173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4111173139Srwatson &bar0->adapter_control); 4112173139Srwatson val64 = val64 | ( XGE_HAL_ADAPTER_EOI_TX_ON | 4113173139Srwatson XGE_HAL_ADAPTER_LED_ON ); 4114171095Ssam } 4115171095Ssam 4116171095Ssam val64 = val64 | XGE_HAL_ADAPTER_CNTL_EN; /* adapter enable */ 4117171095Ssam val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */ 4118171095Ssam xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, val64, 4119173139Srwatson &bar0->adapter_control); 4120171095Ssam 4121171095Ssam /* We spin here waiting for the Link to come up. 4122171095Ssam * This is the fix for the Link being unstable after the reset. */ 4123171095Ssam i = 0; 4124171095Ssam j = 0; 4125171095Ssam do 4126171095Ssam { 4127173139Srwatson adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4128173139Srwatson &bar0->adapter_status); 4129171095Ssam 4130173139Srwatson /* Read the adapter control register for Adapter_enable bit */ 4131173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4132173139Srwatson &bar0->adapter_control); 4133173139Srwatson if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 4134173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) && 4135173139Srwatson (val64 & XGE_HAL_ADAPTER_CNTL_EN)) { 4136173139Srwatson j++; 4137173139Srwatson if (j >= hldev->config.link_valid_cnt) { 4138173139Srwatson if (xge_hal_device_status(hldev, &adp_status) == 4139173139Srwatson XGE_HAL_OK) { 4140173139Srwatson if (__hal_verify_pcc_idle(hldev, 4141173139Srwatson adp_status) != XGE_HAL_OK) { 4142173139Srwatson return 4143173139Srwatson XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4144173139Srwatson } 4145173139Srwatson xge_debug_device(XGE_TRACE, 4146173139Srwatson "adp_status: "XGE_OS_LLXFMT 4147173139Srwatson ", link is up on " 4148173139Srwatson "adapter enable!", 4149173139Srwatson (unsigned long long)adp_status); 4150173139Srwatson val64 = xge_os_pio_mem_read64( 4151173139Srwatson hldev->pdev, 4152173139Srwatson hldev->regh0, 4153173139Srwatson &bar0->adapter_control); 4154173139Srwatson val64 = val64| 4155173139Srwatson (XGE_HAL_ADAPTER_EOI_TX_ON | 4156173139Srwatson XGE_HAL_ADAPTER_LED_ON ); 4157173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 4158173139Srwatson hldev->regh0, val64, 4159173139Srwatson &bar0->adapter_control); 4160173139Srwatson xge_os_mdelay(1); 4161171095Ssam 4162173139Srwatson val64 = xge_os_pio_mem_read64( 4163173139Srwatson hldev->pdev, 4164173139Srwatson hldev->regh0, 4165173139Srwatson &bar0->adapter_control); 4166173139Srwatson break; /* out of for loop */ 4167173139Srwatson } else { 4168173139Srwatson return 4169173139Srwatson XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4170173139Srwatson } 4171173139Srwatson } 4172173139Srwatson } else { 4173173139Srwatson j = 0; /* Reset the count */ 4174173139Srwatson /* Turn on the Laser */ 4175173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4176173139Srwatson &bar0->adapter_control); 4177173139Srwatson val64 = val64 | XGE_HAL_ADAPTER_EOI_TX_ON; 4178173139Srwatson xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, 4179173139Srwatson val64, &bar0->adapter_control); 4180171095Ssam 4181173139Srwatson xge_os_mdelay(1); 4182171095Ssam 4183173139Srwatson /* Now re-enable it as due to noise, hardware 4184173139Srwatson * turned it off */ 4185173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4186173139Srwatson &bar0->adapter_control); 4187173139Srwatson val64 |= XGE_HAL_ADAPTER_CNTL_EN; 4188173139Srwatson val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN);/*ECC enable*/ 4189173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4190173139Srwatson &bar0->adapter_control); 4191173139Srwatson } 4192173139Srwatson xge_os_mdelay(1); /* Sleep for 1 msec */ 4193173139Srwatson i++; 4194171095Ssam } while (i < hldev->config.link_retry_cnt); 4195171095Ssam 4196171095Ssam __hal_device_led_actifity_fix(hldev); 4197171095Ssam 4198171095Ssam#ifndef XGE_HAL_PROCESS_LINK_INT_IN_ISR 4199171095Ssam /* Here we are performing soft reset on XGXS to force link down. 4200171095Ssam * Since link is already up, we will get link state change 4201171095Ssam * poll notificatoin after adapter is enabled */ 4202171095Ssam 4203171095Ssam __hal_serial_mem_write64(hldev, 0x80010515001E0000ULL, 4204173139Srwatson &bar0->dtx_control); 4205171095Ssam (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); 4206171095Ssam 4207171095Ssam __hal_serial_mem_write64(hldev, 0x80010515001E00E0ULL, 4208173139Srwatson &bar0->dtx_control); 4209171095Ssam (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); 4210171095Ssam 4211171095Ssam __hal_serial_mem_write64(hldev, 0x80070515001F00E4ULL, 4212173139Srwatson &bar0->dtx_control); 4213171095Ssam (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); 4214171095Ssam 4215171095Ssam xge_os_mdelay(100); /* Sleep for 500 msec */ 4216171095Ssam#else 4217171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 4218171095Ssam#endif 4219171095Ssam { 4220173139Srwatson /* 4221173139Srwatson * With some switches the link state change interrupt does not 4222173139Srwatson * occur even though the xgxs reset is done as per SPN-006. So, 4223173139Srwatson * poll the adapter status register and check if the link state 4224173139Srwatson * is ok. 4225173139Srwatson */ 4226173139Srwatson adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4227173139Srwatson &bar0->adapter_status); 4228173139Srwatson if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 4229173139Srwatson XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT))) 4230173139Srwatson { 4231173139Srwatson xge_debug_device(XGE_TRACE, "%s", 4232173139Srwatson "enable device causing link state change ind.."); 4233173139Srwatson (void) __hal_device_handle_link_state_change(hldev); 4234173139Srwatson } 4235171095Ssam } 4236171095Ssam 4237171095Ssam if (hldev->config.stats_refresh_time_sec != 4238171095Ssam XGE_HAL_STATS_REFRESH_DISABLE) 4239171095Ssam __hal_stats_enable(&hldev->stats); 4240171095Ssam 4241171095Ssam return XGE_HAL_OK; 4242171095Ssam} 4243171095Ssam 4244171095Ssam/** 4245171095Ssam * xge_hal_device_disable - Disable Xframe adapter. 4246171095Ssam * @hldev: Device handle. 4247171095Ssam * 4248171095Ssam * Disable this device. To gracefully reset the adapter, the host should: 4249171095Ssam * 4250173139Srwatson * - call xge_hal_device_disable(); 4251171095Ssam * 4252173139Srwatson * - call xge_hal_device_intr_disable(); 4253171095Ssam * 4254173139Srwatson * - close all opened channels and clean up outstanding resources; 4255171095Ssam * 4256173139Srwatson * - do some work (error recovery, change mtu, reset, etc); 4257171095Ssam * 4258173139Srwatson * - call xge_hal_device_enable(); 4259171095Ssam * 4260173139Srwatson * - open channels, replenish RxDs, etc. 4261171095Ssam * 4262173139Srwatson * - call xge_hal_device_intr_enable(). 4263171095Ssam * 4264171095Ssam * Note: Disabling the device does _not_ include disabling of interrupts. 4265171095Ssam * After disabling the device stops receiving new frames but those frames 4266171095Ssam * that were already in the pipe will keep coming for some few milliseconds. 4267171095Ssam * 4268171095Ssam * Returns: XGE_HAL_OK - success. 4269171095Ssam * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to 4270171095Ssam * a "quiescent" state. 4271171095Ssam * 4272171095Ssam * See also: xge_hal_status_e{}. 4273171095Ssam */ 4274171095Ssamxge_hal_status_e 4275171095Ssamxge_hal_device_disable(xge_hal_device_t *hldev) 4276171095Ssam{ 4277171095Ssam xge_hal_status_e status = XGE_HAL_OK; 4278171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4279171095Ssam u64 val64; 4280171095Ssam 4281171095Ssam xge_debug_device(XGE_TRACE, "%s", "turn off laser, cleanup hardware"); 4282171095Ssam 4283171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4284171095Ssam &bar0->adapter_control); 4285171095Ssam val64 = val64 & (~XGE_HAL_ADAPTER_CNTL_EN); 4286171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4287171095Ssam &bar0->adapter_control); 4288171095Ssam 4289171095Ssam if (__hal_device_wait_quiescent(hldev, &val64) != XGE_HAL_OK) { 4290173139Srwatson status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4291171095Ssam } 4292171095Ssam 4293171095Ssam if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1, 4294173139Srwatson XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT, 4295173139Srwatson XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4296173139Srwatson xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!"); 4297173139Srwatson status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4298171095Ssam } 4299171095Ssam 4300171095Ssam if (hldev->config.stats_refresh_time_sec != 4301171095Ssam XGE_HAL_STATS_REFRESH_DISABLE) 4302173139Srwatson __hal_stats_disable(&hldev->stats); 4303171095Ssam#ifdef XGE_DEBUG_ASSERT 4304173139Srwatson else 4305171095Ssam xge_assert(!hldev->stats.is_enabled); 4306171095Ssam#endif 4307171095Ssam 4308171095Ssam#ifndef XGE_HAL_DONT_DISABLE_BUS_MASTER_ON_STOP 4309171095Ssam __hal_device_bus_master_disable(hldev); 4310171095Ssam#endif 4311171095Ssam 4312171095Ssam return status; 4313171095Ssam} 4314171095Ssam 4315171095Ssam/** 4316171095Ssam * xge_hal_device_reset - Reset device. 4317171095Ssam * @hldev: HAL device handle. 4318171095Ssam * 4319171095Ssam * Soft-reset the device, reset the device stats except reset_cnt. 4320171095Ssam * 4321171095Ssam * After reset is done, will try to re-initialize HW. 4322171095Ssam * 4323171095Ssam * Returns: XGE_HAL_OK - success. 4324171095Ssam * XGE_HAL_ERR_DEVICE_NOT_INITIALIZED - Device is not initialized. 4325171095Ssam * XGE_HAL_ERR_RESET_FAILED - Reset failed. 4326171095Ssam * 4327171095Ssam * See also: xge_hal_status_e{}. 4328171095Ssam */ 4329171095Ssamxge_hal_status_e 4330171095Ssamxge_hal_device_reset(xge_hal_device_t *hldev) 4331171095Ssam{ 4332171095Ssam xge_hal_status_e status; 4333171095Ssam 4334171095Ssam /* increment the soft reset counter */ 4335171095Ssam u32 reset_cnt = hldev->stats.sw_dev_info_stats.soft_reset_cnt; 4336171095Ssam 4337171095Ssam xge_debug_device(XGE_TRACE, "%s (%d)", "resetting the device", reset_cnt); 4338171095Ssam 4339171095Ssam if (!hldev->is_initialized) 4340173139Srwatson return XGE_HAL_ERR_DEVICE_NOT_INITIALIZED; 4341171095Ssam 4342171095Ssam /* actual "soft" reset of the adapter */ 4343171095Ssam status = __hal_device_reset(hldev); 4344171095Ssam 4345171095Ssam /* reset all stats including saved */ 4346171095Ssam __hal_stats_soft_reset(hldev, 1); 4347171095Ssam 4348171095Ssam /* increment reset counter */ 4349171095Ssam hldev->stats.sw_dev_info_stats.soft_reset_cnt = reset_cnt + 1; 4350171095Ssam 4351171095Ssam /* re-initialize rxufca_intr_thres */ 4352171095Ssam hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres; 4353171095Ssam 4354173139Srwatson hldev->reset_needed_after_close = 0; 4355171095Ssam 4356171095Ssam return status; 4357171095Ssam} 4358171095Ssam 4359171095Ssam/** 4360171095Ssam * xge_hal_device_status - Check whether Xframe hardware is ready for 4361171095Ssam * operation. 4362171095Ssam * @hldev: HAL device handle. 4363171095Ssam * @hw_status: Xframe status register. Returned by HAL. 4364171095Ssam * 4365171095Ssam * Check whether Xframe hardware is ready for operation. 4366171095Ssam * The checking includes TDMA, RDMA, PFC, PIC, MC_DRAM, and the rest 4367171095Ssam * hardware functional blocks. 4368171095Ssam * 4369171095Ssam * Returns: XGE_HAL_OK if the device is ready for operation. Otherwise 4370171095Ssam * returns XGE_HAL_FAIL. Also, fills in adapter status (in @hw_status). 4371171095Ssam * 4372171095Ssam * See also: xge_hal_status_e{}. 4373171095Ssam * Usage: See ex_open{}. 4374171095Ssam */ 4375171095Ssamxge_hal_status_e 4376171095Ssamxge_hal_device_status(xge_hal_device_t *hldev, u64 *hw_status) 4377171095Ssam{ 4378171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4379171095Ssam u64 tmp64; 4380171095Ssam 4381171095Ssam tmp64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4382171095Ssam &bar0->adapter_status); 4383171095Ssam 4384171095Ssam *hw_status = tmp64; 4385171095Ssam 4386171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TDMA_READY)) { 4387173139Srwatson xge_debug_device(XGE_TRACE, "%s", "TDMA is not ready!"); 4388173139Srwatson return XGE_HAL_FAIL; 4389171095Ssam } 4390171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_RDMA_READY)) { 4391173139Srwatson xge_debug_device(XGE_TRACE, "%s", "RDMA is not ready!"); 4392173139Srwatson return XGE_HAL_FAIL; 4393171095Ssam } 4394171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PFC_READY)) { 4395173139Srwatson xge_debug_device(XGE_TRACE, "%s", "PFC is not ready!"); 4396173139Srwatson return XGE_HAL_FAIL; 4397171095Ssam } 4398171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY)) { 4399173139Srwatson xge_debug_device(XGE_TRACE, "%s", "TMAC BUF is not empty!"); 4400173139Srwatson return XGE_HAL_FAIL; 4401171095Ssam } 4402171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT)) { 4403173139Srwatson xge_debug_device(XGE_TRACE, "%s", "PIC is not QUIESCENT!"); 4404173139Srwatson return XGE_HAL_FAIL; 4405171095Ssam } 4406171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY)) { 4407173139Srwatson xge_debug_device(XGE_TRACE, "%s", "MC_DRAM is not ready!"); 4408173139Srwatson return XGE_HAL_FAIL; 4409171095Ssam } 4410171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY)) { 4411173139Srwatson xge_debug_device(XGE_TRACE, "%s", "MC_QUEUES is not ready!"); 4412173139Srwatson return XGE_HAL_FAIL; 4413171095Ssam } 4414171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK)) { 4415173139Srwatson xge_debug_device(XGE_TRACE, "%s", "M_PLL is not locked!"); 4416173139Srwatson return XGE_HAL_FAIL; 4417171095Ssam } 4418171095Ssam#ifndef XGE_HAL_HERC_EMULATION 4419171095Ssam /* 4420171095Ssam * Andrew: in PCI 33 mode, the P_PLL is not used, and therefore, 4421218909Sbrucec * the P_PLL_LOCK bit in the adapter_status register will 4422171095Ssam * not be asserted. 4423171095Ssam */ 4424171095Ssam if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK) && 4425171095Ssam xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC && 4426171095Ssam hldev->pci_mode != XGE_HAL_PCI_33MHZ_MODE) { 4427173139Srwatson xge_debug_device(XGE_TRACE, "%s", "P_PLL is not locked!"); 4428173139Srwatson return XGE_HAL_FAIL; 4429171095Ssam } 4430171095Ssam#endif 4431171095Ssam 4432171095Ssam return XGE_HAL_OK; 4433171095Ssam} 4434171095Ssam 4435171095Ssamvoid 4436171095Ssam__hal_device_msi_intr_endis(xge_hal_device_t *hldev, int flag) 4437171095Ssam{ 4438171095Ssam u16 msi_control_reg; 4439171095Ssam 4440171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 4441171095Ssam xge_offsetof(xge_hal_pci_config_le_t, 4442173139Srwatson msi_control), &msi_control_reg); 4443171095Ssam 4444171095Ssam if (flag) 4445173139Srwatson msi_control_reg |= 0x1; 4446171095Ssam else 4447173139Srwatson msi_control_reg &= ~0x1; 4448171095Ssam 4449171095Ssam xge_os_pci_write16(hldev->pdev, hldev->cfgh, 4450171095Ssam xge_offsetof(xge_hal_pci_config_le_t, 4451173139Srwatson msi_control), msi_control_reg); 4452171095Ssam} 4453171095Ssam 4454171095Ssamvoid 4455171095Ssam__hal_device_msix_intr_endis(xge_hal_device_t *hldev, 4456173139Srwatson xge_hal_channel_t *channel, int flag) 4457171095Ssam{ 4458171095Ssam u64 val64; 4459171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 4460171095Ssam 4461171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4462173139Srwatson &bar0->xmsi_mask_reg); 4463171095Ssam 4464171095Ssam if (flag) 4465173139Srwatson val64 &= ~(1LL << ( 63 - channel->msix_idx )); 4466171095Ssam else 4467173139Srwatson val64 |= (1LL << ( 63 - channel->msix_idx )); 4468171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4469173139Srwatson &bar0->xmsi_mask_reg); 4470171095Ssam} 4471171095Ssam 4472171095Ssam/** 4473171095Ssam * xge_hal_device_intr_enable - Enable Xframe interrupts. 4474171095Ssam * @hldev: HAL device handle. 4475171095Ssam * @op: One of the xge_hal_device_intr_e enumerated values specifying 4476171095Ssam * the type(s) of interrupts to enable. 4477171095Ssam * 4478171095Ssam * Enable Xframe interrupts. The function is to be executed the last in 4479171095Ssam * Xframe initialization sequence. 4480171095Ssam * 4481171095Ssam * See also: xge_hal_device_intr_disable() 4482171095Ssam */ 4483171095Ssamvoid 4484171095Ssamxge_hal_device_intr_enable(xge_hal_device_t *hldev) 4485171095Ssam{ 4486171095Ssam xge_list_t *item; 4487171095Ssam u64 val64; 4488171095Ssam 4489171095Ssam /* PRC initialization and configuration */ 4490171095Ssam xge_list_for_each(item, &hldev->ring_channels) { 4491173139Srwatson xge_hal_channel_h channel; 4492173139Srwatson channel = xge_container_of(item, xge_hal_channel_t, item); 4493173139Srwatson __hal_ring_prc_enable(channel); 4494171095Ssam } 4495171095Ssam 4496171095Ssam /* enable traffic only interrupts */ 4497171095Ssam if (hldev->config.intr_mode != XGE_HAL_INTR_MODE_IRQLINE) { 4498173139Srwatson /* 4499173139Srwatson * make sure all interrupts going to be disabled if MSI 4500173139Srwatson * is enabled. 4501173139Srwatson */ 4502173139Srwatson __hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0); 4503171095Ssam } else { 4504173139Srwatson /* 4505173139Srwatson * Enable the Tx traffic interrupts only if the TTI feature is 4506173139Srwatson * enabled. 4507173139Srwatson */ 4508173139Srwatson val64 = 0; 4509173139Srwatson if (hldev->tti_enabled) 4510173139Srwatson val64 = XGE_HAL_TX_TRAFFIC_INTR; 4511171095Ssam 4512173139Srwatson if (!hldev->config.bimodal_interrupts) 4513173139Srwatson val64 |= XGE_HAL_RX_TRAFFIC_INTR; 4514171095Ssam 4515173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 4516173139Srwatson val64 |= XGE_HAL_RX_TRAFFIC_INTR; 4517171095Ssam 4518173139Srwatson val64 |=XGE_HAL_TX_PIC_INTR | 4519173139Srwatson XGE_HAL_MC_INTR | 4520173139Srwatson XGE_HAL_TX_DMA_INTR | 4521173139Srwatson (hldev->config.sched_timer_us != 4522173139Srwatson XGE_HAL_SCHED_TIMER_DISABLED ? XGE_HAL_SCHED_INTR : 0); 4523173139Srwatson __hal_device_intr_mgmt(hldev, val64, 1); 4524171095Ssam } 4525171095Ssam 4526171095Ssam /* 4527171095Ssam * Enable MSI-X interrupts 4528171095Ssam */ 4529171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 4530171095Ssam 4531173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 4532173139Srwatson /* 4533173139Srwatson * To enable MSI-X, MSI also needs to be enabled, 4534173139Srwatson * due to a bug in the herc NIC. 4535173139Srwatson */ 4536173139Srwatson __hal_device_msi_intr_endis(hldev, 1); 4537173139Srwatson } 4538171095Ssam 4539171095Ssam 4540173139Srwatson /* Enable the MSI-X interrupt for each configured channel */ 4541173139Srwatson xge_list_for_each(item, &hldev->fifo_channels) { 4542173139Srwatson xge_hal_channel_t *channel; 4543171095Ssam 4544173139Srwatson channel = xge_container_of(item, 4545173139Srwatson xge_hal_channel_t, item); 4546171095Ssam 4547173139Srwatson /* 0 vector is reserved for alarms */ 4548173139Srwatson if (!channel->msix_idx) 4549173139Srwatson continue; 4550171095Ssam 4551173139Srwatson __hal_device_msix_intr_endis(hldev, channel, 1); 4552173139Srwatson } 4553171095Ssam 4554173139Srwatson xge_list_for_each(item, &hldev->ring_channels) { 4555173139Srwatson xge_hal_channel_t *channel; 4556171095Ssam 4557173139Srwatson channel = xge_container_of(item, 4558173139Srwatson xge_hal_channel_t, item); 4559171095Ssam 4560173139Srwatson /* 0 vector is reserved for alarms */ 4561173139Srwatson if (!channel->msix_idx) 4562173139Srwatson continue; 4563171095Ssam 4564173139Srwatson __hal_device_msix_intr_endis(hldev, channel, 1); 4565173139Srwatson } 4566171095Ssam } 4567171095Ssam 4568171095Ssam xge_debug_device(XGE_TRACE, "%s", "interrupts are enabled"); 4569171095Ssam} 4570171095Ssam 4571171095Ssam 4572171095Ssam/** 4573171095Ssam * xge_hal_device_intr_disable - Disable Xframe interrupts. 4574171095Ssam * @hldev: HAL device handle. 4575171095Ssam * @op: One of the xge_hal_device_intr_e enumerated values specifying 4576171095Ssam * the type(s) of interrupts to disable. 4577171095Ssam * 4578171095Ssam * Disable Xframe interrupts. 4579171095Ssam * 4580171095Ssam * See also: xge_hal_device_intr_enable() 4581171095Ssam */ 4582171095Ssamvoid 4583171095Ssamxge_hal_device_intr_disable(xge_hal_device_t *hldev) 4584171095Ssam{ 4585171095Ssam xge_list_t *item; 4586171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4587171095Ssam u64 val64; 4588171095Ssam 4589171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 4590171095Ssam 4591173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 4592173139Srwatson /* 4593173139Srwatson * To disable MSI-X, MSI also needs to be disabled, 4594173139Srwatson * due to a bug in the herc NIC. 4595173139Srwatson */ 4596173139Srwatson __hal_device_msi_intr_endis(hldev, 0); 4597173139Srwatson } 4598171095Ssam 4599173139Srwatson /* Disable the MSI-X interrupt for each configured channel */ 4600173139Srwatson xge_list_for_each(item, &hldev->fifo_channels) { 4601173139Srwatson xge_hal_channel_t *channel; 4602171095Ssam 4603173139Srwatson channel = xge_container_of(item, 4604173139Srwatson xge_hal_channel_t, item); 4605171095Ssam 4606173139Srwatson /* 0 vector is reserved for alarms */ 4607173139Srwatson if (!channel->msix_idx) 4608173139Srwatson continue; 4609171095Ssam 4610173139Srwatson __hal_device_msix_intr_endis(hldev, channel, 0); 4611171095Ssam 4612173139Srwatson } 4613171095Ssam 4614173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 4615173139Srwatson hldev->regh0, 0xFFFFFFFFFFFFFFFFULL, 4616173139Srwatson &bar0->tx_traffic_mask); 4617171095Ssam 4618173139Srwatson xge_list_for_each(item, &hldev->ring_channels) { 4619173139Srwatson xge_hal_channel_t *channel; 4620171095Ssam 4621173139Srwatson channel = xge_container_of(item, 4622173139Srwatson xge_hal_channel_t, item); 4623171095Ssam 4624173139Srwatson /* 0 vector is reserved for alarms */ 4625173139Srwatson if (!channel->msix_idx) 4626173139Srwatson continue; 4627171095Ssam 4628173139Srwatson __hal_device_msix_intr_endis(hldev, channel, 0); 4629173139Srwatson } 4630171095Ssam 4631173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 4632173139Srwatson hldev->regh0, 0xFFFFFFFFFFFFFFFFULL, 4633173139Srwatson &bar0->rx_traffic_mask); 4634171095Ssam } 4635171095Ssam 4636171095Ssam /* 4637171095Ssam * Disable traffic only interrupts. 4638171095Ssam * Tx traffic interrupts are used only if the TTI feature is 4639171095Ssam * enabled. 4640171095Ssam */ 4641171095Ssam val64 = 0; 4642171095Ssam if (hldev->tti_enabled) 4643173139Srwatson val64 = XGE_HAL_TX_TRAFFIC_INTR; 4644171095Ssam 4645171095Ssam val64 |= XGE_HAL_RX_TRAFFIC_INTR | 4646173139Srwatson XGE_HAL_TX_PIC_INTR | 4647173139Srwatson XGE_HAL_MC_INTR | 4648173139Srwatson (hldev->config.sched_timer_us != XGE_HAL_SCHED_TIMER_DISABLED ? 4649173139Srwatson XGE_HAL_SCHED_INTR : 0); 4650171095Ssam __hal_device_intr_mgmt(hldev, val64, 0); 4651171095Ssam 4652171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4653171095Ssam 0xFFFFFFFFFFFFFFFFULL, 4654173139Srwatson &bar0->general_int_mask); 4655171095Ssam 4656171095Ssam 4657171095Ssam /* disable all configured PRCs */ 4658171095Ssam xge_list_for_each(item, &hldev->ring_channels) { 4659173139Srwatson xge_hal_channel_h channel; 4660173139Srwatson channel = xge_container_of(item, xge_hal_channel_t, item); 4661173139Srwatson __hal_ring_prc_disable(channel); 4662171095Ssam } 4663171095Ssam 4664171095Ssam xge_debug_device(XGE_TRACE, "%s", "interrupts are disabled"); 4665171095Ssam} 4666171095Ssam 4667171095Ssam 4668171095Ssam/** 4669171095Ssam * xge_hal_device_mcast_enable - Enable Xframe multicast addresses. 4670171095Ssam * @hldev: HAL device handle. 4671171095Ssam * 4672171095Ssam * Enable Xframe multicast addresses. 4673171095Ssam * Returns: XGE_HAL_OK on success. 4674171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to enable mcast 4675171095Ssam * feature within the time(timeout). 4676171095Ssam * 4677171095Ssam * See also: xge_hal_device_mcast_disable(), xge_hal_status_e{}. 4678171095Ssam */ 4679171095Ssamxge_hal_status_e 4680171095Ssamxge_hal_device_mcast_enable(xge_hal_device_t *hldev) 4681171095Ssam{ 4682171095Ssam u64 val64; 4683171095Ssam xge_hal_pci_bar0_t *bar0; 4684171095Ssam int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET; 4685171095Ssam 4686171095Ssam if (hldev == NULL) 4687173139Srwatson return XGE_HAL_ERR_INVALID_DEVICE; 4688171095Ssam 4689171095Ssam if (hldev->mcast_refcnt) 4690173139Srwatson return XGE_HAL_OK; 4691171095Ssam 4692171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 4693173139Srwatson mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC; 4694171095Ssam 4695171095Ssam hldev->mcast_refcnt = 1; 4696171095Ssam 4697171095Ssam bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4698171095Ssam 4699171095Ssam /* Enable all Multicast addresses */ 4700171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4701171095Ssam XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0x010203040506ULL), 4702171095Ssam &bar0->rmac_addr_data0_mem); 4703171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4704171095Ssam XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0xfeffffffffffULL), 4705171095Ssam &bar0->rmac_addr_data1_mem); 4706171095Ssam val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE | 4707173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4708173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset); 4709171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4710173139Srwatson &bar0->rmac_addr_cmd_mem); 4711171095Ssam 4712171095Ssam if (__hal_device_register_poll(hldev, 4713173139Srwatson &bar0->rmac_addr_cmd_mem, 0, 4714173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4715173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4716173139Srwatson /* upper layer may require to repeat */ 4717173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4718171095Ssam } 4719171095Ssam 4720171095Ssam return XGE_HAL_OK; 4721171095Ssam} 4722171095Ssam 4723171095Ssam/** 4724171095Ssam * xge_hal_device_mcast_disable - Disable Xframe multicast addresses. 4725171095Ssam * @hldev: HAL device handle. 4726171095Ssam * 4727171095Ssam * Disable Xframe multicast addresses. 4728171095Ssam * Returns: XGE_HAL_OK - success. 4729171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to disable mcast 4730171095Ssam * feature within the time(timeout). 4731171095Ssam * 4732171095Ssam * See also: xge_hal_device_mcast_enable(), xge_hal_status_e{}. 4733171095Ssam */ 4734171095Ssamxge_hal_status_e 4735171095Ssamxge_hal_device_mcast_disable(xge_hal_device_t *hldev) 4736171095Ssam{ 4737171095Ssam u64 val64; 4738171095Ssam xge_hal_pci_bar0_t *bar0; 4739171095Ssam int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET; 4740171095Ssam 4741171095Ssam if (hldev == NULL) 4742173139Srwatson return XGE_HAL_ERR_INVALID_DEVICE; 4743171095Ssam 4744171095Ssam if (hldev->mcast_refcnt == 0) 4745173139Srwatson return XGE_HAL_OK; 4746171095Ssam 4747171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 4748173139Srwatson mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC; 4749171095Ssam 4750171095Ssam hldev->mcast_refcnt = 0; 4751171095Ssam 4752171095Ssam bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4753171095Ssam 4754171095Ssam /* Disable all Multicast addresses */ 4755171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4756171095Ssam XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0xffffffffffffULL), 4757173139Srwatson &bar0->rmac_addr_data0_mem); 4758171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4759171095Ssam XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0), 4760173139Srwatson &bar0->rmac_addr_data1_mem); 4761171095Ssam 4762171095Ssam val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE | 4763173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4764173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset); 4765171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4766173139Srwatson &bar0->rmac_addr_cmd_mem); 4767171095Ssam 4768171095Ssam if (__hal_device_register_poll(hldev, 4769173139Srwatson &bar0->rmac_addr_cmd_mem, 0, 4770173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4771173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4772173139Srwatson /* upper layer may require to repeat */ 4773173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4774171095Ssam } 4775171095Ssam 4776171095Ssam return XGE_HAL_OK; 4777171095Ssam} 4778171095Ssam 4779171095Ssam/** 4780171095Ssam * xge_hal_device_promisc_enable - Enable promiscuous mode. 4781171095Ssam * @hldev: HAL device handle. 4782171095Ssam * 4783171095Ssam * Enable promiscuous mode of Xframe operation. 4784171095Ssam * 4785171095Ssam * See also: xge_hal_device_promisc_disable(). 4786171095Ssam */ 4787171095Ssamvoid 4788171095Ssamxge_hal_device_promisc_enable(xge_hal_device_t *hldev) 4789171095Ssam{ 4790171095Ssam u64 val64; 4791171095Ssam xge_hal_pci_bar0_t *bar0; 4792171095Ssam 4793171095Ssam xge_assert(hldev); 4794171095Ssam 4795171095Ssam bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4796171095Ssam 4797171095Ssam if (!hldev->is_promisc) { 4798173139Srwatson /* Put the NIC into promiscuous mode */ 4799173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4800173139Srwatson &bar0->mac_cfg); 4801173139Srwatson val64 |= XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE; 4802171095Ssam 4803173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4804173139Srwatson XGE_HAL_RMAC_CFG_KEY(0x4C0D), 4805173139Srwatson &bar0->rmac_cfg_key); 4806171095Ssam 4807173139Srwatson __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 4808173139Srwatson (u32)(val64 >> 32), 4809173139Srwatson &bar0->mac_cfg); 4810171095Ssam 4811173139Srwatson hldev->is_promisc = 1; 4812173139Srwatson xge_debug_device(XGE_TRACE, 4813173139Srwatson "mac_cfg 0x"XGE_OS_LLXFMT": promisc enabled", 4814173139Srwatson (unsigned long long)val64); 4815171095Ssam } 4816171095Ssam} 4817171095Ssam 4818171095Ssam/** 4819171095Ssam * xge_hal_device_promisc_disable - Disable promiscuous mode. 4820171095Ssam * @hldev: HAL device handle. 4821171095Ssam * 4822171095Ssam * Disable promiscuous mode of Xframe operation. 4823171095Ssam * 4824171095Ssam * See also: xge_hal_device_promisc_enable(). 4825171095Ssam */ 4826171095Ssamvoid 4827171095Ssamxge_hal_device_promisc_disable(xge_hal_device_t *hldev) 4828171095Ssam{ 4829171095Ssam u64 val64; 4830171095Ssam xge_hal_pci_bar0_t *bar0; 4831171095Ssam 4832171095Ssam xge_assert(hldev); 4833171095Ssam 4834171095Ssam bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4835171095Ssam 4836171095Ssam if (hldev->is_promisc) { 4837173139Srwatson /* Remove the NIC from promiscuous mode */ 4838173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4839173139Srwatson &bar0->mac_cfg); 4840173139Srwatson val64 &= ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE; 4841171095Ssam 4842173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4843173139Srwatson XGE_HAL_RMAC_CFG_KEY(0x4C0D), 4844173139Srwatson &bar0->rmac_cfg_key); 4845171095Ssam 4846173139Srwatson __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 4847173139Srwatson (u32)(val64 >> 32), 4848173139Srwatson &bar0->mac_cfg); 4849171095Ssam 4850173139Srwatson hldev->is_promisc = 0; 4851173139Srwatson xge_debug_device(XGE_TRACE, 4852173139Srwatson "mac_cfg 0x"XGE_OS_LLXFMT": promisc disabled", 4853173139Srwatson (unsigned long long)val64); 4854171095Ssam } 4855171095Ssam} 4856171095Ssam 4857171095Ssam/** 4858171095Ssam * xge_hal_device_macaddr_get - Get MAC addresses. 4859171095Ssam * @hldev: HAL device handle. 4860171095Ssam * @index: MAC address index, in the range from 0 to 4861171095Ssam * XGE_HAL_MAX_MAC_ADDRESSES. 4862171095Ssam * @macaddr: MAC address. Returned by HAL. 4863171095Ssam * 4864171095Ssam * Retrieve one of the stored MAC addresses by reading non-volatile 4865171095Ssam * memory on the chip. 4866171095Ssam * 4867171095Ssam * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported. 4868171095Ssam * 4869171095Ssam * Returns: XGE_HAL_OK - success. 4870171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac 4871171095Ssam * address within the time(timeout). 4872171095Ssam * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. 4873171095Ssam * 4874171095Ssam * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}. 4875171095Ssam */ 4876171095Ssamxge_hal_status_e 4877171095Ssamxge_hal_device_macaddr_get(xge_hal_device_t *hldev, int index, 4878173139Srwatson macaddr_t *macaddr) 4879171095Ssam{ 4880173139Srwatson xge_hal_pci_bar0_t *bar0; 4881171095Ssam u64 val64; 4882171095Ssam int i; 4883171095Ssam 4884171095Ssam if (hldev == NULL) { 4885173139Srwatson return XGE_HAL_ERR_INVALID_DEVICE; 4886171095Ssam } 4887171095Ssam 4888173139Srwatson bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4889173139Srwatson 4890171095Ssam if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) { 4891173139Srwatson return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 4892171095Ssam } 4893171095Ssam 4894171095Ssam#ifdef XGE_HAL_HERC_EMULATION 4895171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000010000000000, 4896171095Ssam &bar0->rmac_addr_data0_mem); 4897171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000000000000000, 4898171095Ssam &bar0->rmac_addr_data1_mem); 4899173139Srwatson val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_RD | 4900173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4901173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)); 4902171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4903171095Ssam &bar0->rmac_addr_cmd_mem); 4904171095Ssam 4905173139Srwatson /* poll until done */ 4906171095Ssam __hal_device_register_poll(hldev, 4907173139Srwatson &bar0->rmac_addr_cmd_mem, 0, 4908173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD, 4909173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS); 4910171095Ssam 4911171095Ssam#endif 4912171095Ssam 4913171095Ssam val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_RD | 4914173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4915173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) ); 4916171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4917171095Ssam &bar0->rmac_addr_cmd_mem); 4918171095Ssam 4919171095Ssam if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0, 4920173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4921173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4922173139Srwatson /* upper layer may require to repeat */ 4923173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4924171095Ssam } 4925171095Ssam 4926171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4927171095Ssam &bar0->rmac_addr_data0_mem); 4928171095Ssam for (i=0; i < XGE_HAL_ETH_ALEN; i++) { 4929173139Srwatson (*macaddr)[i] = (u8)(val64 >> ((64 - 8) - (i * 8))); 4930171095Ssam } 4931171095Ssam 4932171095Ssam#ifdef XGE_HAL_HERC_EMULATION 4933171095Ssam for (i=0; i < XGE_HAL_ETH_ALEN; i++) { 4934173139Srwatson (*macaddr)[i] = (u8)0; 4935171095Ssam } 4936171095Ssam (*macaddr)[1] = (u8)1; 4937171095Ssam 4938171095Ssam#endif 4939171095Ssam 4940171095Ssam return XGE_HAL_OK; 4941171095Ssam} 4942171095Ssam 4943171095Ssam/** 4944171095Ssam * xge_hal_device_macaddr_set - Set MAC address. 4945171095Ssam * @hldev: HAL device handle. 4946171095Ssam * @index: MAC address index, in the range from 0 to 4947171095Ssam * XGE_HAL_MAX_MAC_ADDRESSES. 4948171095Ssam * @macaddr: New MAC address to configure. 4949171095Ssam * 4950171095Ssam * Configure one of the available MAC address "slots". 4951171095Ssam * 4952171095Ssam * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported. 4953171095Ssam * 4954171095Ssam * Returns: XGE_HAL_OK - success. 4955171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac 4956171095Ssam * address within the time(timeout). 4957171095Ssam * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. 4958171095Ssam * 4959171095Ssam * See also: xge_hal_device_macaddr_get(), xge_hal_status_e{}. 4960171095Ssam */ 4961171095Ssamxge_hal_status_e 4962171095Ssamxge_hal_device_macaddr_set(xge_hal_device_t *hldev, int index, 4963173139Srwatson macaddr_t macaddr) 4964171095Ssam{ 4965171095Ssam xge_hal_pci_bar0_t *bar0 = 4966173139Srwatson (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4967171095Ssam u64 val64, temp64; 4968171095Ssam int i; 4969171095Ssam 4970171095Ssam if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) 4971173139Srwatson return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 4972171095Ssam 4973171095Ssam temp64 = 0; 4974171095Ssam for (i=0; i < XGE_HAL_ETH_ALEN; i++) { 4975173139Srwatson temp64 |= macaddr[i]; 4976173139Srwatson temp64 <<= 8; 4977171095Ssam } 4978171095Ssam temp64 >>= 8; 4979171095Ssam 4980171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4981171095Ssam XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(temp64), 4982173139Srwatson &bar0->rmac_addr_data0_mem); 4983171095Ssam 4984171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4985171095Ssam XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0ULL), 4986173139Srwatson &bar0->rmac_addr_data1_mem); 4987171095Ssam 4988171095Ssam val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_WE | 4989173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4990173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) ); 4991171095Ssam 4992171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4993171095Ssam &bar0->rmac_addr_cmd_mem); 4994171095Ssam 4995171095Ssam if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0, 4996173139Srwatson XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4997173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4998173139Srwatson /* upper layer may require to repeat */ 4999173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 5000171095Ssam } 5001171095Ssam 5002171095Ssam return XGE_HAL_OK; 5003171095Ssam} 5004171095Ssam 5005171095Ssam/** 5006171095Ssam * xge_hal_device_macaddr_clear - Set MAC address. 5007171095Ssam * @hldev: HAL device handle. 5008171095Ssam * @index: MAC address index, in the range from 0 to 5009171095Ssam * XGE_HAL_MAX_MAC_ADDRESSES. 5010171095Ssam * 5011171095Ssam * Clear one of the available MAC address "slots". 5012171095Ssam * 5013171095Ssam * Returns: XGE_HAL_OK - success. 5014171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac 5015171095Ssam * address within the time(timeout). 5016171095Ssam * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. 5017171095Ssam * 5018171095Ssam * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}. 5019171095Ssam */ 5020171095Ssamxge_hal_status_e 5021171095Ssamxge_hal_device_macaddr_clear(xge_hal_device_t *hldev, int index) 5022171095Ssam{ 5023171095Ssam xge_hal_status_e status; 5024171095Ssam u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 5025171095Ssam 5026171095Ssam status = xge_hal_device_macaddr_set(hldev, index, macaddr); 5027171095Ssam if (status != XGE_HAL_OK) { 5028173139Srwatson xge_debug_device(XGE_ERR, "%s", 5029173139Srwatson "Not able to set the mac addr"); 5030173139Srwatson return status; 5031171095Ssam } 5032171095Ssam 5033171095Ssam return XGE_HAL_OK; 5034171095Ssam} 5035171095Ssam 5036171095Ssam/** 5037171095Ssam * xge_hal_device_macaddr_find - Finds index in the rmac table. 5038171095Ssam * @hldev: HAL device handle. 5039171095Ssam * @wanted: Wanted MAC address. 5040171095Ssam * 5041171095Ssam * See also: xge_hal_device_macaddr_set(). 5042171095Ssam */ 5043171095Ssamint 5044171095Ssamxge_hal_device_macaddr_find(xge_hal_device_t *hldev, macaddr_t wanted) 5045171095Ssam{ 5046171095Ssam int i; 5047171095Ssam 5048171095Ssam if (hldev == NULL) { 5049173139Srwatson return XGE_HAL_ERR_INVALID_DEVICE; 5050171095Ssam } 5051171095Ssam 5052171095Ssam for (i=1; i<XGE_HAL_MAX_MAC_ADDRESSES; i++) { 5053173139Srwatson macaddr_t macaddr; 5054173139Srwatson (void) xge_hal_device_macaddr_get(hldev, i, &macaddr); 5055173139Srwatson if (!xge_os_memcmp(macaddr, wanted, sizeof(macaddr_t))) { 5056173139Srwatson return i; 5057173139Srwatson } 5058171095Ssam } 5059171095Ssam 5060171095Ssam return -1; 5061171095Ssam} 5062171095Ssam 5063171095Ssam/** 5064171095Ssam * xge_hal_device_mtu_set - Set MTU. 5065171095Ssam * @hldev: HAL device handle. 5066171095Ssam * @new_mtu: New MTU size to configure. 5067171095Ssam * 5068171095Ssam * Set new MTU value. Example, to use jumbo frames: 5069171095Ssam * xge_hal_device_mtu_set(my_device, my_channel, 9600); 5070171095Ssam * 5071171095Ssam * Returns: XGE_HAL_OK on success. 5072171095Ssam * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control 5073171095Ssam * register. 5074171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to initialize TTI/RTI 5075171095Ssam * schemes. 5076171095Ssam * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to 5077171095Ssam * a "quiescent" state. 5078171095Ssam */ 5079171095Ssamxge_hal_status_e 5080171095Ssamxge_hal_device_mtu_set(xge_hal_device_t *hldev, int new_mtu) 5081171095Ssam{ 5082171095Ssam xge_hal_status_e status; 5083171095Ssam 5084171095Ssam /* 5085171095Ssam * reset needed if 1) new MTU differs, and 5086171095Ssam * 2a) device was closed or 5087171095Ssam * 2b) device is being upped for first time. 5088171095Ssam */ 5089171095Ssam if (hldev->config.mtu != new_mtu) { 5090173139Srwatson if (hldev->reset_needed_after_close || 5091173139Srwatson !hldev->mtu_first_time_set) { 5092173139Srwatson status = xge_hal_device_reset(hldev); 5093173139Srwatson if (status != XGE_HAL_OK) { 5094173139Srwatson xge_debug_device(XGE_TRACE, "%s", 5095173139Srwatson "fatal: can not reset the device"); 5096173139Srwatson return status; 5097173139Srwatson } 5098173139Srwatson } 5099173139Srwatson /* store the new MTU in device, reset will use it */ 5100173139Srwatson hldev->config.mtu = new_mtu; 5101173139Srwatson xge_debug_device(XGE_TRACE, "new MTU %d applied", 5102173139Srwatson new_mtu); 5103171095Ssam } 5104171095Ssam 5105171095Ssam if (!hldev->mtu_first_time_set) 5106173139Srwatson hldev->mtu_first_time_set = 1; 5107171095Ssam 5108171095Ssam return XGE_HAL_OK; 5109171095Ssam} 5110171095Ssam 5111171095Ssam/** 5112171095Ssam * xge_hal_device_initialize - Initialize Xframe device. 5113171095Ssam * @hldev: HAL device handle. 5114171095Ssam * @attr: pointer to xge_hal_device_attr_t structure 5115171095Ssam * @device_config: Configuration to be _applied_ to the device, 5116171095Ssam * For the Xframe configuration "knobs" please 5117171095Ssam * refer to xge_hal_device_config_t and Xframe 5118171095Ssam * User Guide. 5119171095Ssam * 5120171095Ssam * Initialize Xframe device. Note that all the arguments of this public API 5121171095Ssam * are 'IN', including @hldev. Upper-layer driver (ULD) cooperates with 5122171095Ssam * OS to find new Xframe device, locate its PCI and memory spaces. 5123171095Ssam * 5124171095Ssam * When done, the ULD allocates sizeof(xge_hal_device_t) bytes for HAL 5125171095Ssam * to enable the latter to perform Xframe hardware initialization. 5126171095Ssam * 5127171095Ssam * Returns: XGE_HAL_OK - success. 5128171095Ssam * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - Driver is not initialized. 5129171095Ssam * XGE_HAL_ERR_BAD_DEVICE_CONFIG - Device configuration params are not 5130171095Ssam * valid. 5131171095Ssam * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed. 5132171095Ssam * XGE_HAL_ERR_BAD_SUBSYSTEM_ID - Device subsystem id is invalid. 5133171095Ssam * XGE_HAL_ERR_INVALID_MAC_ADDRESS - Device mac address in not valid. 5134171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac 5135171095Ssam * address within the time(timeout) or TTI/RTI initialization failed. 5136171095Ssam * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control. 5137171095Ssam * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT -Device is not queiscent. 5138171095Ssam * 5139171095Ssam * See also: xge_hal_device_terminate(), xge_hal_status_e{} 5140171095Ssam * xge_hal_device_attr_t{}. 5141171095Ssam */ 5142171095Ssamxge_hal_status_e 5143171095Ssamxge_hal_device_initialize(xge_hal_device_t *hldev, xge_hal_device_attr_t *attr, 5144173139Srwatson xge_hal_device_config_t *device_config) 5145171095Ssam{ 5146171095Ssam int i; 5147171095Ssam xge_hal_status_e status; 5148171095Ssam xge_hal_channel_t *channel; 5149171095Ssam u16 subsys_device; 5150171095Ssam u16 subsys_vendor; 5151171095Ssam int total_dram_size, ring_auto_dram_cfg, left_dram_size; 5152171095Ssam int total_dram_size_max = 0; 5153171095Ssam 5154171095Ssam xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is initializing", 5155173139Srwatson (unsigned long long)(ulong_t)hldev); 5156171095Ssam 5157171095Ssam /* sanity check */ 5158171095Ssam if (g_xge_hal_driver == NULL || 5159171095Ssam !g_xge_hal_driver->is_initialized) { 5160173139Srwatson return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED; 5161171095Ssam } 5162171095Ssam 5163171095Ssam xge_os_memzero(hldev, sizeof(xge_hal_device_t)); 5164171095Ssam 5165171095Ssam /* 5166171095Ssam * validate a common part of Xframe-I/II configuration 5167171095Ssam * (and run check_card() later, once PCI inited - see below) 5168171095Ssam */ 5169171095Ssam status = __hal_device_config_check_common(device_config); 5170171095Ssam if (status != XGE_HAL_OK) 5171173139Srwatson return status; 5172171095Ssam 5173171095Ssam /* apply config */ 5174171095Ssam xge_os_memcpy(&hldev->config, device_config, 5175173139Srwatson sizeof(xge_hal_device_config_t)); 5176171095Ssam 5177171095Ssam /* save original attr */ 5178171095Ssam xge_os_memcpy(&hldev->orig_attr, attr, 5179173139Srwatson sizeof(xge_hal_device_attr_t)); 5180171095Ssam 5181171095Ssam /* initialize rxufca_intr_thres */ 5182171095Ssam hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres; 5183171095Ssam 5184171095Ssam hldev->regh0 = attr->regh0; 5185171095Ssam hldev->regh1 = attr->regh1; 5186171095Ssam hldev->regh2 = attr->regh2; 5187171095Ssam hldev->isrbar0 = hldev->bar0 = attr->bar0; 5188171095Ssam hldev->bar1 = attr->bar1; 5189171095Ssam hldev->bar2 = attr->bar2; 5190171095Ssam hldev->pdev = attr->pdev; 5191171095Ssam hldev->irqh = attr->irqh; 5192171095Ssam hldev->cfgh = attr->cfgh; 5193171095Ssam 5194171095Ssam /* set initial bimodal timer for bimodal adaptive schema */ 5195171095Ssam hldev->bimodal_timer_val_us = hldev->config.bimodal_timer_lo_us; 5196171095Ssam 5197171095Ssam hldev->queueh = xge_queue_create(hldev->pdev, hldev->irqh, 5198173139Srwatson g_xge_hal_driver->config.queue_size_initial, 5199173139Srwatson g_xge_hal_driver->config.queue_size_max, 5200173139Srwatson __hal_device_event_queued, hldev); 5201171095Ssam if (hldev->queueh == NULL) 5202173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 5203171095Ssam 5204171095Ssam hldev->magic = XGE_HAL_MAGIC; 5205171095Ssam 5206171095Ssam xge_assert(hldev->regh0); 5207171095Ssam xge_assert(hldev->regh1); 5208171095Ssam xge_assert(hldev->bar0); 5209171095Ssam xge_assert(hldev->bar1); 5210171095Ssam xge_assert(hldev->pdev); 5211171095Ssam xge_assert(hldev->irqh); 5212171095Ssam xge_assert(hldev->cfgh); 5213171095Ssam 5214171095Ssam /* initialize some PCI/PCI-X fields of this PCI device. */ 5215171095Ssam __hal_device_pci_init(hldev); 5216171095Ssam 5217171095Ssam /* 5218171095Ssam * initlialize lists to properly handling a potential 5219171095Ssam * terminate request 5220171095Ssam */ 5221171095Ssam xge_list_init(&hldev->free_channels); 5222171095Ssam xge_list_init(&hldev->fifo_channels); 5223171095Ssam xge_list_init(&hldev->ring_channels); 5224171095Ssam 5225171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 5226173139Srwatson /* fixups for xena */ 5227173139Srwatson hldev->config.rth_en = 0; 5228173139Srwatson hldev->config.rth_spdm_en = 0; 5229173139Srwatson hldev->config.rts_mac_en = 0; 5230173139Srwatson total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_XENA; 5231171095Ssam 5232173139Srwatson status = __hal_device_config_check_xena(device_config); 5233173139Srwatson if (status != XGE_HAL_OK) { 5234173139Srwatson xge_hal_device_terminate(hldev); 5235173139Srwatson return status; 5236173139Srwatson } 5237173139Srwatson if (hldev->config.bimodal_interrupts == 1) { 5238173139Srwatson xge_hal_device_terminate(hldev); 5239173139Srwatson return XGE_HAL_BADCFG_BIMODAL_XENA_NOT_ALLOWED; 5240173139Srwatson } else if (hldev->config.bimodal_interrupts == 5241173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) 5242173139Srwatson hldev->config.bimodal_interrupts = 0; 5243171095Ssam } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 5244173139Srwatson /* fixups for herc */ 5245173139Srwatson total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_HERC; 5246173139Srwatson status = __hal_device_config_check_herc(device_config); 5247173139Srwatson if (status != XGE_HAL_OK) { 5248173139Srwatson xge_hal_device_terminate(hldev); 5249173139Srwatson return status; 5250173139Srwatson } 5251173139Srwatson if (hldev->config.bimodal_interrupts == 5252173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) 5253173139Srwatson hldev->config.bimodal_interrupts = 1; 5254171095Ssam } else { 5255173139Srwatson xge_debug_device(XGE_ERR, 5256173139Srwatson "detected unknown device_id 0x%x", hldev->device_id); 5257173139Srwatson xge_hal_device_terminate(hldev); 5258173139Srwatson return XGE_HAL_ERR_BAD_DEVICE_ID; 5259171095Ssam } 5260171095Ssam 5261171095Ssam /* allocate and initialize FIFO types of channels according to 5262171095Ssam * configuration */ 5263171095Ssam for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { 5264173139Srwatson if (!device_config->fifo.queue[i].configured) 5265173139Srwatson continue; 5266171095Ssam 5267173139Srwatson channel = __hal_channel_allocate(hldev, i, 5268173139Srwatson XGE_HAL_CHANNEL_TYPE_FIFO); 5269173139Srwatson if (channel == NULL) { 5270173139Srwatson xge_debug_device(XGE_ERR, 5271173139Srwatson "fifo: __hal_channel_allocate failed"); 5272173139Srwatson xge_hal_device_terminate(hldev); 5273173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 5274173139Srwatson } 5275173139Srwatson /* add new channel to the device */ 5276173139Srwatson xge_list_insert(&channel->item, &hldev->free_channels); 5277171095Ssam } 5278171095Ssam 5279171095Ssam /* 5280171095Ssam * automatic DRAM adjustment 5281171095Ssam */ 5282171095Ssam total_dram_size = 0; 5283171095Ssam ring_auto_dram_cfg = 0; 5284171095Ssam for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 5285173139Srwatson if (!device_config->ring.queue[i].configured) 5286173139Srwatson continue; 5287173139Srwatson if (device_config->ring.queue[i].dram_size_mb == 5288173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) { 5289173139Srwatson ring_auto_dram_cfg++; 5290173139Srwatson continue; 5291173139Srwatson } 5292173139Srwatson total_dram_size += device_config->ring.queue[i].dram_size_mb; 5293171095Ssam } 5294171095Ssam left_dram_size = total_dram_size_max - total_dram_size; 5295171095Ssam if (left_dram_size < 0 || 5296171095Ssam (ring_auto_dram_cfg && left_dram_size / ring_auto_dram_cfg == 0)) { 5297173139Srwatson xge_debug_device(XGE_ERR, 5298173139Srwatson "ring config: exceeded DRAM size %d MB", 5299173139Srwatson total_dram_size_max); 5300173139Srwatson xge_hal_device_terminate(hldev); 5301173139Srwatson return XGE_HAL_BADCFG_RING_QUEUE_SIZE; 5302173139Srwatson } 5303171095Ssam 5304171095Ssam /* 5305171095Ssam * allocate and initialize RING types of channels according to 5306171095Ssam * configuration 5307171095Ssam */ 5308171095Ssam for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 5309173139Srwatson if (!device_config->ring.queue[i].configured) 5310173139Srwatson continue; 5311171095Ssam 5312173139Srwatson if (device_config->ring.queue[i].dram_size_mb == 5313173139Srwatson XGE_HAL_DEFAULT_USE_HARDCODE) { 5314173139Srwatson hldev->config.ring.queue[i].dram_size_mb = 5315173139Srwatson device_config->ring.queue[i].dram_size_mb = 5316173139Srwatson left_dram_size / ring_auto_dram_cfg; 5317173139Srwatson } 5318171095Ssam 5319173139Srwatson channel = __hal_channel_allocate(hldev, i, 5320173139Srwatson XGE_HAL_CHANNEL_TYPE_RING); 5321173139Srwatson if (channel == NULL) { 5322173139Srwatson xge_debug_device(XGE_ERR, 5323173139Srwatson "ring: __hal_channel_allocate failed"); 5324173139Srwatson xge_hal_device_terminate(hldev); 5325173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 5326173139Srwatson } 5327173139Srwatson /* add new channel to the device */ 5328173139Srwatson xge_list_insert(&channel->item, &hldev->free_channels); 5329171095Ssam } 5330171095Ssam 5331171095Ssam /* get subsystem IDs */ 5332171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 5333173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), 5334173139Srwatson &subsys_device); 5335171095Ssam xge_os_pci_read16(hldev->pdev, hldev->cfgh, 5336173139Srwatson xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id), 5337173139Srwatson &subsys_vendor); 5338171095Ssam xge_debug_device(XGE_TRACE, 5339173139Srwatson "subsystem_id %04x:%04x", 5340173139Srwatson subsys_vendor, subsys_device); 5341171095Ssam 5342171095Ssam /* reset device initially */ 5343171095Ssam (void) __hal_device_reset(hldev); 5344171095Ssam 5345171095Ssam /* set host endian before, to assure proper action */ 5346171095Ssam status = __hal_device_set_swapper(hldev); 5347171095Ssam if (status != XGE_HAL_OK) { 5348173139Srwatson xge_debug_device(XGE_ERR, 5349173139Srwatson "__hal_device_set_swapper failed"); 5350173139Srwatson xge_hal_device_terminate(hldev); 5351173139Srwatson (void) __hal_device_reset(hldev); 5352173139Srwatson return status; 5353171095Ssam } 5354171095Ssam 5355171095Ssam#ifndef XGE_HAL_HERC_EMULATION 5356171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 5357173139Srwatson __hal_device_xena_fix_mac(hldev); 5358171095Ssam#endif 5359171095Ssam 5360171095Ssam /* MAC address initialization. 5361171095Ssam * For now only one mac address will be read and used. */ 5362171095Ssam status = xge_hal_device_macaddr_get(hldev, 0, &hldev->macaddr[0]); 5363171095Ssam if (status != XGE_HAL_OK) { 5364173139Srwatson xge_debug_device(XGE_ERR, 5365173139Srwatson "xge_hal_device_macaddr_get failed"); 5366173139Srwatson xge_hal_device_terminate(hldev); 5367173139Srwatson return status; 5368171095Ssam } 5369171095Ssam 5370171095Ssam if (hldev->macaddr[0][0] == 0xFF && 5371171095Ssam hldev->macaddr[0][1] == 0xFF && 5372171095Ssam hldev->macaddr[0][2] == 0xFF && 5373171095Ssam hldev->macaddr[0][3] == 0xFF && 5374171095Ssam hldev->macaddr[0][4] == 0xFF && 5375171095Ssam hldev->macaddr[0][5] == 0xFF) { 5376173139Srwatson xge_debug_device(XGE_ERR, 5377173139Srwatson "xge_hal_device_macaddr_get returns all FFs"); 5378173139Srwatson xge_hal_device_terminate(hldev); 5379173139Srwatson return XGE_HAL_ERR_INVALID_MAC_ADDRESS; 5380171095Ssam } 5381171095Ssam 5382171095Ssam xge_debug_device(XGE_TRACE, 5383173139Srwatson "default macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x", 5384173139Srwatson hldev->macaddr[0][0], hldev->macaddr[0][1], 5385173139Srwatson hldev->macaddr[0][2], hldev->macaddr[0][3], 5386173139Srwatson hldev->macaddr[0][4], hldev->macaddr[0][5]); 5387171095Ssam 5388171095Ssam status = __hal_stats_initialize(&hldev->stats, hldev); 5389171095Ssam if (status != XGE_HAL_OK) { 5390173139Srwatson xge_debug_device(XGE_ERR, 5391173139Srwatson "__hal_stats_initialize failed"); 5392173139Srwatson xge_hal_device_terminate(hldev); 5393173139Srwatson return status; 5394171095Ssam } 5395171095Ssam 5396171095Ssam status = __hal_device_hw_initialize(hldev); 5397171095Ssam if (status != XGE_HAL_OK) { 5398173139Srwatson xge_debug_device(XGE_ERR, 5399173139Srwatson "__hal_device_hw_initialize failed"); 5400173139Srwatson xge_hal_device_terminate(hldev); 5401173139Srwatson return status; 5402171095Ssam } 5403171095Ssam hldev->dump_buf=(char*)xge_os_malloc(hldev->pdev, XGE_HAL_DUMP_BUF_SIZE); 5404171095Ssam if (hldev->dump_buf == NULL) { 5405173139Srwatson xge_debug_device(XGE_ERR, 5406173139Srwatson "__hal_device_hw_initialize failed"); 5407173139Srwatson xge_hal_device_terminate(hldev); 5408173139Srwatson return XGE_HAL_ERR_OUT_OF_MEMORY; 5409171095Ssam } 5410171095Ssam 5411171095Ssam 5412171095Ssam /* Xena-only: need to serialize fifo posts across all device fifos */ 5413171095Ssam#if defined(XGE_HAL_TX_MULTI_POST) 5414171095Ssam xge_os_spin_lock_init(&hldev->xena_post_lock, hldev->pdev); 5415171095Ssam#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) 5416171095Ssam xge_os_spin_lock_init_irq(&hldev->xena_post_lock, hldev->irqh); 5417171095Ssam#endif 5418171095Ssam /* Getting VPD data */ 5419173139Srwatson __hal_device_get_vpd_data(hldev); 5420171095Ssam 5421171095Ssam hldev->is_initialized = 1; 5422171095Ssam 5423171095Ssam return XGE_HAL_OK; 5424171095Ssam} 5425171095Ssam 5426171095Ssam/** 5427171095Ssam * xge_hal_device_terminating - Mark the device as 'terminating'. 5428171095Ssam * @devh: HAL device handle. 5429171095Ssam * 5430171095Ssam * Mark the device as 'terminating', going to terminate. Can be used 5431171095Ssam * to serialize termination with other running processes/contexts. 5432171095Ssam * 5433171095Ssam * See also: xge_hal_device_terminate(). 5434171095Ssam */ 5435171095Ssamvoid 5436171095Ssamxge_hal_device_terminating(xge_hal_device_h devh) 5437171095Ssam{ 5438171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 5439173139Srwatson xge_list_t *item; 5440173139Srwatson xge_hal_channel_t *channel; 5441173139Srwatson#if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) 5442173139Srwatson unsigned long flags=0; 5443173139Srwatson#endif 5444173139Srwatson 5445173139Srwatson /* 5446173139Srwatson * go through each opened tx channel and aquire 5447173139Srwatson * lock, so it will serialize with HAL termination flag 5448173139Srwatson */ 5449173139Srwatson xge_list_for_each(item, &hldev->fifo_channels) { 5450173139Srwatson channel = xge_container_of(item, xge_hal_channel_t, item); 5451173139Srwatson#if defined(XGE_HAL_TX_MULTI_RESERVE) 5452173139Srwatson xge_os_spin_lock(&channel->reserve_lock); 5453173139Srwatson#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) 5454173139Srwatson xge_os_spin_lock_irq(&channel->reserve_lock, flags); 5455173139Srwatson#endif 5456173139Srwatson 5457173139Srwatson channel->terminating = 1; 5458173139Srwatson 5459173139Srwatson#if defined(XGE_HAL_TX_MULTI_RESERVE) 5460173139Srwatson xge_os_spin_unlock(&channel->reserve_lock); 5461173139Srwatson#elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) 5462173139Srwatson xge_os_spin_unlock_irq(&channel->reserve_lock, flags); 5463173139Srwatson#endif 5464173139Srwatson } 5465173139Srwatson 5466171095Ssam hldev->terminating = 1; 5467171095Ssam} 5468171095Ssam 5469171095Ssam/** 5470171095Ssam * xge_hal_device_terminate - Terminate Xframe device. 5471171095Ssam * @hldev: HAL device handle. 5472171095Ssam * 5473171095Ssam * Terminate HAL device. 5474171095Ssam * 5475171095Ssam * See also: xge_hal_device_initialize(). 5476171095Ssam */ 5477171095Ssamvoid 5478171095Ssamxge_hal_device_terminate(xge_hal_device_t *hldev) 5479171095Ssam{ 5480171095Ssam xge_assert(g_xge_hal_driver != NULL); 5481171095Ssam xge_assert(hldev != NULL); 5482171095Ssam xge_assert(hldev->magic == XGE_HAL_MAGIC); 5483171095Ssam 5484171095Ssam xge_queue_flush(hldev->queueh); 5485171095Ssam 5486171095Ssam hldev->terminating = 1; 5487171095Ssam hldev->is_initialized = 0; 5488173139Srwatson hldev->in_poll = 0; 5489171095Ssam hldev->magic = XGE_HAL_DEAD; 5490171095Ssam 5491171095Ssam#if defined(XGE_HAL_TX_MULTI_POST) 5492171095Ssam xge_os_spin_lock_destroy(&hldev->xena_post_lock, hldev->pdev); 5493171095Ssam#elif defined(XGE_HAL_TX_MULTI_POST_IRQ) 5494171095Ssam xge_os_spin_lock_destroy_irq(&hldev->xena_post_lock, hldev->pdev); 5495171095Ssam#endif 5496171095Ssam 5497171095Ssam xge_debug_device(XGE_TRACE, "device "XGE_OS_LLXFMT" is terminating", 5498173139Srwatson (unsigned long long)(ulong_t)hldev); 5499171095Ssam 5500171095Ssam xge_assert(xge_list_is_empty(&hldev->fifo_channels)); 5501171095Ssam xge_assert(xge_list_is_empty(&hldev->ring_channels)); 5502171095Ssam 5503171095Ssam if (hldev->stats.is_initialized) { 5504173139Srwatson __hal_stats_terminate(&hldev->stats); 5505171095Ssam } 5506171095Ssam 5507171095Ssam /* close if open and free all channels */ 5508171095Ssam while (!xge_list_is_empty(&hldev->free_channels)) { 5509173139Srwatson xge_hal_channel_t *channel = (xge_hal_channel_t*) 5510173139Srwatson hldev->free_channels.next; 5511171095Ssam 5512173139Srwatson xge_assert(!channel->is_open); 5513173139Srwatson xge_list_remove(&channel->item); 5514173139Srwatson __hal_channel_free(channel); 5515171095Ssam } 5516171095Ssam 5517171095Ssam if (hldev->queueh) { 5518173139Srwatson xge_queue_destroy(hldev->queueh); 5519171095Ssam } 5520171095Ssam 5521171095Ssam if (hldev->spdm_table) { 5522173139Srwatson xge_os_free(hldev->pdev, 5523173139Srwatson hldev->spdm_table[0], 5524173139Srwatson (sizeof(xge_hal_spdm_entry_t) * 5525173139Srwatson hldev->spdm_max_entries)); 5526173139Srwatson xge_os_free(hldev->pdev, 5527173139Srwatson hldev->spdm_table, 5528173139Srwatson (sizeof(xge_hal_spdm_entry_t *) * 5529173139Srwatson hldev->spdm_max_entries)); 5530173139Srwatson xge_os_spin_lock_destroy(&hldev->spdm_lock, hldev->pdev); 5531173139Srwatson hldev->spdm_table = NULL; 5532171095Ssam } 5533171095Ssam 5534171095Ssam if (hldev->dump_buf) { 5535171095Ssam xge_os_free(hldev->pdev, hldev->dump_buf, 5536173139Srwatson XGE_HAL_DUMP_BUF_SIZE); 5537173139Srwatson hldev->dump_buf = NULL; 5538171095Ssam } 5539171095Ssam 5540171095Ssam if (hldev->device_id != 0) { 5541173139Srwatson int j, pcisize; 5542171095Ssam 5543173139Srwatson pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)? 5544173139Srwatson XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA; 5545173139Srwatson for (j = 0; j < pcisize; j++) { 5546173139Srwatson xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4, 5547173139Srwatson *((u32*)&hldev->pci_config_space_bios + j)); 5548173139Srwatson } 5549171095Ssam } 5550171095Ssam} 5551171095Ssam/** 5552171095Ssam * __hal_device_get_vpd_data - Getting vpd_data. 5553171095Ssam * 5554171095Ssam * @hldev: HAL device handle. 5555171095Ssam * 5556171095Ssam * Getting product name and serial number from vpd capabilites structure 5557171095Ssam * 5558171095Ssam */ 5559171095Ssamvoid 5560171095Ssam__hal_device_get_vpd_data(xge_hal_device_t *hldev) 5561171095Ssam{ 5562173139Srwatson u8 * vpd_data; 5563173139Srwatson u8 data; 5564173139Srwatson int index = 0, count, fail = 0; 5565173139Srwatson u8 vpd_addr = XGE_HAL_CARD_XENA_VPD_ADDR; 5566173139Srwatson if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 5567173139Srwatson vpd_addr = XGE_HAL_CARD_HERC_VPD_ADDR; 5568171095Ssam 5569173139Srwatson xge_os_strcpy((char *) hldev->vpd_data.product_name, 5570173139Srwatson "10 Gigabit Ethernet Adapter"); 5571173139Srwatson xge_os_strcpy((char *) hldev->vpd_data.serial_num, "not available"); 5572171095Ssam 5573173139Srwatson vpd_data = ( u8*) xge_os_malloc(hldev->pdev, XGE_HAL_VPD_BUFFER_SIZE + 16); 5574173139Srwatson if ( vpd_data == 0 ) 5575173139Srwatson return; 5576171095Ssam 5577173139Srwatson for (index = 0; index < XGE_HAL_VPD_BUFFER_SIZE; index +=4 ) { 5578173139Srwatson xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 2), (u8)index); 5579173139Srwatson xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 2), &data); 5580173139Srwatson xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 3), 0); 5581173139Srwatson for (count = 0; count < 5; count++ ) { 5582173139Srwatson xge_os_mdelay(2); 5583173139Srwatson xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 3), &data); 5584173139Srwatson if (data == XGE_HAL_VPD_READ_COMPLETE) 5585173139Srwatson break; 5586173139Srwatson } 5587171095Ssam 5588173139Srwatson if (count >= 5) { 5589173139Srwatson xge_os_printf("ERR, Reading VPD data failed"); 5590173139Srwatson fail = 1; 5591173139Srwatson break; 5592173139Srwatson } 5593171095Ssam 5594173139Srwatson xge_os_pci_read32(hldev->pdev, hldev->cfgh,(vpd_addr + 4), 5595173139Srwatson (u32 *)&vpd_data[index]); 5596173139Srwatson } 5597173139Srwatson 5598173139Srwatson if(!fail) { 5599171095Ssam 5600173139Srwatson /* read serial number of adapter */ 5601173139Srwatson for (count = 0; count < XGE_HAL_VPD_BUFFER_SIZE; count++) { 5602173139Srwatson if ((vpd_data[count] == 'S') && 5603173139Srwatson (vpd_data[count + 1] == 'N') && 5604173139Srwatson (vpd_data[count + 2] < XGE_HAL_VPD_LENGTH)) { 5605173139Srwatson memset(hldev->vpd_data.serial_num, 0, XGE_HAL_VPD_LENGTH); 5606173139Srwatson memcpy(hldev->vpd_data.serial_num, &vpd_data[count + 3], 5607173139Srwatson vpd_data[count + 2]); 5608173139Srwatson break; 5609173139Srwatson } 5610173139Srwatson } 5611171095Ssam 5612173139Srwatson if (vpd_data[1] < XGE_HAL_VPD_LENGTH) { 5613173139Srwatson memset(hldev->vpd_data.product_name, 0, vpd_data[1]); 5614173139Srwatson memcpy(hldev->vpd_data.product_name, &vpd_data[3], vpd_data[1]); 5615173139Srwatson } 5616171095Ssam 5617173139Srwatson } 5618171095Ssam 5619173139Srwatson xge_os_free(hldev->pdev, vpd_data, XGE_HAL_VPD_BUFFER_SIZE + 16); 5620171095Ssam} 5621171095Ssam 5622173139Srwatson 5623171095Ssam/** 5624171095Ssam * xge_hal_device_handle_tcode - Handle transfer code. 5625171095Ssam * @channelh: Channel handle. 5626171095Ssam * @dtrh: Descriptor handle. 5627171095Ssam * @t_code: One of the enumerated (and documented in the Xframe user guide) 5628171095Ssam * "transfer codes". 5629171095Ssam * 5630171095Ssam * Handle descriptor's transfer code. The latter comes with each completed 5631171095Ssam * descriptor, see xge_hal_fifo_dtr_next_completed() and 5632171095Ssam * xge_hal_ring_dtr_next_completed(). 5633171095Ssam * Transfer codes are enumerated in xgehal-fifo.h and xgehal-ring.h. 5634171095Ssam * 5635171095Ssam * Returns: one of the xge_hal_status_e{} enumerated types. 5636173139Srwatson * XGE_HAL_OK - for success. 5637171095Ssam * XGE_HAL_ERR_CRITICAL - when encounters critical error. 5638171095Ssam */ 5639171095Ssamxge_hal_status_e 5640171095Ssamxge_hal_device_handle_tcode (xge_hal_channel_h channelh, 5641173139Srwatson xge_hal_dtr_h dtrh, u8 t_code) 5642171095Ssam{ 5643171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 5644171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh; 5645171095Ssam 5646171095Ssam if (t_code > 15) { 5647173139Srwatson xge_os_printf("invalid t_code %d", t_code); 5648173139Srwatson return XGE_HAL_OK; 5649171095Ssam } 5650171095Ssam 5651171095Ssam if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 5652171095Ssam hldev->stats.sw_dev_err_stats.txd_t_code_err_cnt[t_code]++; 5653171095Ssam 5654171095Ssam#if defined(XGE_HAL_DEBUG_BAD_TCODE) 5655173139Srwatson xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; 5656173139Srwatson xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":" 5657173139Srwatson XGE_OS_LLXFMT":"XGE_OS_LLXFMT, 5658173139Srwatson txdp->control_1, txdp->control_2, txdp->buffer_pointer, 5659173139Srwatson txdp->host_control); 5660171095Ssam#endif 5661171095Ssam 5662173139Srwatson /* handle link "down" immediately without going through 5663173139Srwatson * xge_hal_device_poll() routine. */ 5664173139Srwatson if (t_code == XGE_HAL_TXD_T_CODE_LOSS_OF_LINK) { 5665173139Srwatson /* link is down */ 5666173139Srwatson if (hldev->link_state != XGE_HAL_LINK_DOWN) { 5667173139Srwatson xge_hal_pci_bar0_t *bar0 = 5668173139Srwatson (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 5669173139Srwatson u64 val64; 5670171095Ssam 5671173139Srwatson hldev->link_state = XGE_HAL_LINK_DOWN; 5672171095Ssam 5673173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, 5674173139Srwatson hldev->regh0, &bar0->adapter_control); 5675171095Ssam 5676173139Srwatson /* turn off LED */ 5677173139Srwatson val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); 5678173139Srwatson xge_os_pio_mem_write64(hldev->pdev, 5679173139Srwatson hldev->regh0, val64, 5680173139Srwatson &bar0->adapter_control); 5681171095Ssam 5682173139Srwatson g_xge_hal_driver->uld_callbacks.link_down( 5683173139Srwatson hldev->upper_layer_info); 5684173139Srwatson } 5685173139Srwatson } else if (t_code == XGE_HAL_TXD_T_CODE_ABORT_BUFFER || 5686173139Srwatson t_code == XGE_HAL_TXD_T_CODE_ABORT_DTOR) { 5687173139Srwatson __hal_device_handle_targetabort(hldev); 5688173139Srwatson return XGE_HAL_ERR_CRITICAL; 5689173139Srwatson } 5690173139Srwatson return XGE_HAL_ERR_PKT_DROP; 5691171095Ssam } else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 5692171095Ssam hldev->stats.sw_dev_err_stats.rxd_t_code_err_cnt[t_code]++; 5693171095Ssam 5694171095Ssam#if defined(XGE_HAL_DEBUG_BAD_TCODE) 5695173139Srwatson xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; 5696173139Srwatson xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT 5697173139Srwatson ":"XGE_OS_LLXFMT, rxdp->control_1, 5698173139Srwatson rxdp->control_2, rxdp->buffer0_ptr, 5699173139Srwatson rxdp->host_control); 5700171095Ssam#endif 5701173139Srwatson if (t_code == XGE_HAL_RXD_T_CODE_BAD_ECC) { 5702173139Srwatson hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 5703173139Srwatson __hal_device_handle_eccerr(hldev, "rxd_t_code", 5704173139Srwatson (u64)t_code); 5705173139Srwatson return XGE_HAL_ERR_CRITICAL; 5706173139Srwatson } else if (t_code == XGE_HAL_RXD_T_CODE_PARITY || 5707173139Srwatson t_code == XGE_HAL_RXD_T_CODE_PARITY_ABORT) { 5708173139Srwatson hldev->stats.sw_dev_err_stats.parity_err_cnt++; 5709173139Srwatson __hal_device_handle_parityerr(hldev, "rxd_t_code", 5710173139Srwatson (u64)t_code); 5711173139Srwatson return XGE_HAL_ERR_CRITICAL; 5712173139Srwatson /* do not drop if detected unknown IPv6 extension */ 5713173139Srwatson } else if (t_code != XGE_HAL_RXD_T_CODE_UNKNOWN_PROTO) { 5714173139Srwatson return XGE_HAL_ERR_PKT_DROP; 5715173139Srwatson } 5716171095Ssam } 5717171095Ssam return XGE_HAL_OK; 5718171095Ssam} 5719171095Ssam 5720171095Ssam/** 5721171095Ssam * xge_hal_device_link_state - Get link state. 5722171095Ssam * @devh: HAL device handle. 5723171095Ssam * @ls: Link state, see xge_hal_device_link_state_e{}. 5724171095Ssam * 5725171095Ssam * Get link state. 5726171095Ssam * Returns: XGE_HAL_OK. 5727171095Ssam * See also: xge_hal_device_link_state_e{}. 5728171095Ssam */ 5729171095Ssamxge_hal_status_e xge_hal_device_link_state(xge_hal_device_h devh, 5730173139Srwatson xge_hal_device_link_state_e *ls) 5731171095Ssam{ 5732171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5733171095Ssam 5734171095Ssam xge_assert(ls != NULL); 5735171095Ssam *ls = hldev->link_state; 5736171095Ssam return XGE_HAL_OK; 5737171095Ssam} 5738171095Ssam 5739171095Ssam/** 5740171095Ssam * xge_hal_device_sched_timer - Configure scheduled device interrupt. 5741171095Ssam * @devh: HAL device handle. 5742171095Ssam * @interval_us: Time interval, in miscoseconds. 5743171095Ssam * Unlike transmit and receive interrupts, 5744171095Ssam * the scheduled interrupt is generated independently of 5745171095Ssam * traffic, but purely based on time. 5746171095Ssam * @one_shot: 1 - generate scheduled interrupt only once. 5747171095Ssam * 0 - generate scheduled interrupt periodically at the specified 5748171095Ssam * @interval_us interval. 5749171095Ssam * 5750171095Ssam * (Re-)configure scheduled interrupt. Can be called at runtime to change 5751171095Ssam * the setting, generate one-shot interrupts based on the resource and/or 5752171095Ssam * traffic conditions, other purposes. 5753171095Ssam * See also: xge_hal_device_config_t{}. 5754171095Ssam */ 5755171095Ssamvoid xge_hal_device_sched_timer(xge_hal_device_h devh, int interval_us, 5756173139Srwatson int one_shot) 5757171095Ssam{ 5758171095Ssam u64 val64; 5759171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5760171095Ssam xge_hal_pci_bar0_t *bar0 = 5761173139Srwatson (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 5762171095Ssam unsigned int interval = hldev->config.pci_freq_mherz * interval_us; 5763171095Ssam 5764171095Ssam interval = __hal_fix_time_ival_herc(hldev, interval); 5765171095Ssam 5766171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 5767173139Srwatson &bar0->scheduled_int_ctrl); 5768171095Ssam if (interval) { 5769173139Srwatson val64 &= XGE_HAL_SCHED_INT_PERIOD_MASK; 5770173139Srwatson val64 |= XGE_HAL_SCHED_INT_PERIOD(interval); 5771173139Srwatson if (one_shot) { 5772173139Srwatson val64 |= XGE_HAL_SCHED_INT_CTRL_ONE_SHOT; 5773173139Srwatson } 5774173139Srwatson val64 |= XGE_HAL_SCHED_INT_CTRL_TIMER_EN; 5775171095Ssam } else { 5776173139Srwatson val64 &= ~XGE_HAL_SCHED_INT_CTRL_TIMER_EN; 5777171095Ssam } 5778171095Ssam 5779171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 5780173139Srwatson val64, &bar0->scheduled_int_ctrl); 5781171095Ssam 5782171095Ssam xge_debug_device(XGE_TRACE, "sched_timer 0x"XGE_OS_LLXFMT": %s", 5783173139Srwatson (unsigned long long)val64, 5784173139Srwatson interval ? "enabled" : "disabled"); 5785171095Ssam} 5786171095Ssam 5787171095Ssam/** 5788171095Ssam * xge_hal_device_check_id - Verify device ID. 5789171095Ssam * @devh: HAL device handle. 5790171095Ssam * 5791171095Ssam * Verify device ID. 5792171095Ssam * Returns: one of the xge_hal_card_e{} enumerated types. 5793171095Ssam * See also: xge_hal_card_e{}. 5794171095Ssam */ 5795171095Ssamxge_hal_card_e 5796171095Ssamxge_hal_device_check_id(xge_hal_device_h devh) 5797171095Ssam{ 5798171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5799171095Ssam switch (hldev->device_id) { 5800171095Ssam case XGE_PCI_DEVICE_ID_XENA_1: 5801171095Ssam case XGE_PCI_DEVICE_ID_XENA_2: 5802173139Srwatson return XGE_HAL_CARD_XENA; 5803171095Ssam case XGE_PCI_DEVICE_ID_HERC_1: 5804171095Ssam case XGE_PCI_DEVICE_ID_HERC_2: 5805173139Srwatson return XGE_HAL_CARD_HERC; 5806171095Ssam case XGE_PCI_DEVICE_ID_TITAN_1: 5807171095Ssam case XGE_PCI_DEVICE_ID_TITAN_2: 5808173139Srwatson return XGE_HAL_CARD_TITAN; 5809171095Ssam default: 5810173139Srwatson return XGE_HAL_CARD_UNKNOWN; 5811171095Ssam } 5812171095Ssam} 5813171095Ssam 5814171095Ssam/** 5815171095Ssam * xge_hal_device_pci_info_get - Get PCI bus informations such as width, 5816173139Srwatson * frequency, and mode from previously stored values. 5817173139Srwatson * @devh: HAL device handle. 5818173139Srwatson * @pci_mode: pointer to a variable of enumerated type 5819173139Srwatson * xge_hal_pci_mode_e{}. 5820173139Srwatson * @bus_frequency: pointer to a variable of enumerated type 5821173139Srwatson * xge_hal_pci_bus_frequency_e{}. 5822173139Srwatson * @bus_width: pointer to a variable of enumerated type 5823173139Srwatson * xge_hal_pci_bus_width_e{}. 5824171095Ssam * 5825171095Ssam * Get pci mode, frequency, and PCI bus width. 5826171095Ssam * Returns: one of the xge_hal_status_e{} enumerated types. 5827173139Srwatson * XGE_HAL_OK - for success. 5828173139Srwatson * XGE_HAL_ERR_INVALID_DEVICE - for invalid device handle. 5829171095Ssam * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e. 5830171095Ssam */ 5831171095Ssamxge_hal_status_e 5832171095Ssamxge_hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, 5833173139Srwatson xge_hal_pci_bus_frequency_e *bus_frequency, 5834173139Srwatson xge_hal_pci_bus_width_e *bus_width) 5835171095Ssam{ 5836171095Ssam xge_hal_status_e rc_status; 5837171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5838171095Ssam 5839171095Ssam if (!hldev || !hldev->is_initialized || hldev->magic != XGE_HAL_MAGIC) { 5840173139Srwatson rc_status = XGE_HAL_ERR_INVALID_DEVICE; 5841173139Srwatson xge_debug_device(XGE_ERR, 5842173139Srwatson "xge_hal_device_pci_info_get error, rc %d for device %p", 5843173139Srwatson rc_status, hldev); 5844171095Ssam 5845173139Srwatson return rc_status; 5846171095Ssam } 5847171095Ssam 5848173139Srwatson *pci_mode = hldev->pci_mode; 5849173139Srwatson *bus_frequency = hldev->bus_frequency; 5850173139Srwatson *bus_width = hldev->bus_width; 5851173139Srwatson rc_status = XGE_HAL_OK; 5852171095Ssam return rc_status; 5853171095Ssam} 5854171095Ssam 5855171095Ssam/** 5856171095Ssam * xge_hal_reinitialize_hw 5857171095Ssam * @hldev: private member of the device structure. 5858171095Ssam * 5859171095Ssam * This function will soft reset the NIC and re-initalize all the 5860171095Ssam * I/O registers to the values they had after it's inital initialization 5861171095Ssam * through the probe function. 5862171095Ssam */ 5863171095Ssamint xge_hal_reinitialize_hw(xge_hal_device_t * hldev) 5864171095Ssam{ 5865171095Ssam (void) xge_hal_device_reset(hldev); 5866171095Ssam if (__hal_device_hw_initialize(hldev) != XGE_HAL_OK) { 5867173139Srwatson xge_hal_device_terminate(hldev); 5868173139Srwatson (void) __hal_device_reset(hldev); 5869173139Srwatson return 1; 5870171095Ssam } 5871171095Ssam return 0; 5872171095Ssam} 5873171095Ssam 5874171095Ssam 5875171095Ssam/* 5876171095Ssam * __hal_read_spdm_entry_line 5877171095Ssam * @hldev: pointer to xge_hal_device_t structure 5878171095Ssam * @spdm_line: spdm line in the spdm entry to be read. 5879171095Ssam * @spdm_entry: spdm entry of the spdm_line in the SPDM table. 5880171095Ssam * @spdm_line_val: Contains the value stored in the spdm line. 5881171095Ssam * 5882171095Ssam * SPDM table contains upto a maximum of 256 spdm entries. 5883171095Ssam * Each spdm entry contains 8 lines and each line stores 8 bytes. 5884171095Ssam * This function reads the spdm line(addressed by @spdm_line) 5885171095Ssam * of the spdm entry(addressed by @spdm_entry) in 5886171095Ssam * the SPDM table. 5887171095Ssam */ 5888171095Ssamxge_hal_status_e 5889171095Ssam__hal_read_spdm_entry_line(xge_hal_device_t *hldev, u8 spdm_line, 5890173139Srwatson u16 spdm_entry, u64 *spdm_line_val) 5891171095Ssam{ 5892171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 5893171095Ssam u64 val64; 5894171095Ssam 5895171095Ssam val64 = XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE | 5896173139Srwatson XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_LINE_SEL(spdm_line) | 5897173139Srwatson XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_OFFSET(spdm_entry); 5898171095Ssam 5899171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 5900173139Srwatson &bar0->rts_rth_spdm_mem_ctrl); 5901171095Ssam 5902171095Ssam /* poll until done */ 5903171095Ssam if (__hal_device_register_poll(hldev, 5904173139Srwatson &bar0->rts_rth_spdm_mem_ctrl, 0, 5905173139Srwatson XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE, 5906173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 5907171095Ssam 5908173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 5909171095Ssam } 5910171095Ssam 5911171095Ssam *spdm_line_val = xge_os_pio_mem_read64(hldev->pdev, 5912173139Srwatson hldev->regh0, &bar0->rts_rth_spdm_mem_data); 5913171095Ssam return XGE_HAL_OK; 5914171095Ssam} 5915171095Ssam 5916171095Ssam 5917171095Ssam/* 5918171095Ssam * __hal_get_free_spdm_entry 5919171095Ssam * @hldev: pointer to xge_hal_device_t structure 5920171095Ssam * @spdm_entry: Contains an index to the unused spdm entry in the SPDM table. 5921171095Ssam * 5922171095Ssam * This function returns an index of unused spdm entry in the SPDM 5923171095Ssam * table. 5924171095Ssam */ 5925171095Ssamstatic xge_hal_status_e 5926171095Ssam__hal_get_free_spdm_entry(xge_hal_device_t *hldev, u16 *spdm_entry) 5927171095Ssam{ 5928171095Ssam xge_hal_status_e status; 5929171095Ssam u64 spdm_line_val=0; 5930171095Ssam 5931171095Ssam /* 5932171095Ssam * Search in the local SPDM table for a free slot. 5933171095Ssam */ 5934171095Ssam *spdm_entry = 0; 5935171095Ssam for(; *spdm_entry < hldev->spdm_max_entries; (*spdm_entry)++) { 5936173139Srwatson if (hldev->spdm_table[*spdm_entry]->in_use) { 5937173139Srwatson break; 5938173139Srwatson } 5939171095Ssam } 5940171095Ssam 5941171095Ssam if (*spdm_entry >= hldev->spdm_max_entries) { 5942173139Srwatson return XGE_HAL_ERR_SPDM_TABLE_FULL; 5943171095Ssam } 5944171095Ssam 5945171095Ssam /* 5946171095Ssam * Make sure that the corresponding spdm entry in the SPDM 5947171095Ssam * table is free. 5948171095Ssam * Seventh line of the spdm entry contains information about 5949171095Ssam * whether the entry is free or not. 5950171095Ssam */ 5951171095Ssam if ((status = __hal_read_spdm_entry_line(hldev, 7, *spdm_entry, 5952173139Srwatson &spdm_line_val)) != XGE_HAL_OK) { 5953173139Srwatson return status; 5954171095Ssam } 5955171095Ssam 5956171095Ssam /* BIT(63) in spdm_line 7 corresponds to entry_enable bit */ 5957171095Ssam if ((spdm_line_val & BIT(63))) { 5958173139Srwatson /* 5959173139Srwatson * Log a warning 5960173139Srwatson */ 5961173139Srwatson xge_debug_device(XGE_ERR, "Local SPDM table is not " 5962173139Srwatson "consistent with the actual one for the spdm " 5963173139Srwatson "entry %d", *spdm_entry); 5964173139Srwatson return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT; 5965171095Ssam } 5966171095Ssam 5967171095Ssam return XGE_HAL_OK; 5968171095Ssam} 5969171095Ssam 5970171095Ssam 5971171095Ssam/* 5972171095Ssam * __hal_calc_jhash - Calculate Jenkins hash. 5973171095Ssam * @msg: Jenkins hash algorithm key. 5974171095Ssam * @length: Length of the key. 5975171095Ssam * @golden_ratio: Jenkins hash golden ratio. 5976171095Ssam * @init_value: Jenkins hash initial value. 5977171095Ssam * 5978171095Ssam * This function implements the Jenkins based algorithm used for the 5979171095Ssam * calculation of the RTH hash. 5980171095Ssam * Returns: Jenkins hash value. 5981171095Ssam * 5982171095Ssam */ 5983171095Ssamstatic u32 5984171095Ssam__hal_calc_jhash(u8 *msg, u32 length, u32 golden_ratio, u32 init_value) 5985171095Ssam{ 5986171095Ssam 5987171095Ssam register u32 a,b,c,len; 5988171095Ssam 5989171095Ssam /* 5990171095Ssam * Set up the internal state 5991171095Ssam */ 5992171095Ssam len = length; 5993171095Ssam a = b = golden_ratio; /* the golden ratio; an arbitrary value */ 5994171095Ssam c = init_value; /* the previous hash value */ 5995171095Ssam 5996171095Ssam /* handle most of the key */ 5997171095Ssam while (len >= 12) 5998171095Ssam { 5999173139Srwatson a += (msg[0] + ((u32)msg[1]<<8) + ((u32)msg[2]<<16) 6000173139Srwatson + ((u32)msg[3]<<24)); 6001173139Srwatson b += (msg[4] + ((u32)msg[5]<<8) + ((u32)msg[6]<<16) 6002173139Srwatson + ((u32)msg[7]<<24)); 6003173139Srwatson c += (msg[8] + ((u32)msg[9]<<8) + ((u32)msg[10]<<16) 6004173139Srwatson + ((u32)msg[11]<<24)); 6005173139Srwatson mix(a,b,c); 6006173139Srwatson msg += 12; len -= 12; 6007171095Ssam } 6008171095Ssam 6009171095Ssam /* handle the last 11 bytes */ 6010171095Ssam c += length; 6011171095Ssam switch(len) /* all the case statements fall through */ 6012171095Ssam { 6013173139Srwatson case 11: c+= ((u32)msg[10]<<24); 6014173139Srwatson break; 6015173139Srwatson case 10: c+= ((u32)msg[9]<<16); 6016173139Srwatson break; 6017173139Srwatson case 9 : c+= ((u32)msg[8]<<8); 6018173139Srwatson break; 6019173139Srwatson /* the first byte of c is reserved for the length */ 6020173139Srwatson case 8 : b+= ((u32)msg[7]<<24); 6021173139Srwatson break; 6022173139Srwatson case 7 : b+= ((u32)msg[6]<<16); 6023173139Srwatson break; 6024173139Srwatson case 6 : b+= ((u32)msg[5]<<8); 6025173139Srwatson break; 6026173139Srwatson case 5 : b+= msg[4]; 6027173139Srwatson break; 6028173139Srwatson case 4 : a+= ((u32)msg[3]<<24); 6029173139Srwatson break; 6030173139Srwatson case 3 : a+= ((u32)msg[2]<<16); 6031173139Srwatson break; 6032173139Srwatson case 2 : a+= ((u32)msg[1]<<8); 6033173139Srwatson break; 6034173139Srwatson case 1 : a+= msg[0]; 6035173139Srwatson break; 6036173139Srwatson /* case 0: nothing left to add */ 6037171095Ssam } 6038171095Ssam 6039171095Ssam mix(a,b,c); 6040171095Ssam 6041171095Ssam /* report the result */ 6042171095Ssam return c; 6043171095Ssam} 6044171095Ssam 6045171095Ssam 6046171095Ssam/** 6047171095Ssam * xge_hal_spdm_entry_add - Add a new entry to the SPDM table. 6048171095Ssam * @devh: HAL device handle. 6049171095Ssam * @src_ip: Source ip address(IPv4/IPv6). 6050171095Ssam * @dst_ip: Destination ip address(IPv4/IPv6). 6051171095Ssam * @l4_sp: L4 source port. 6052171095Ssam * @l4_dp: L4 destination port. 6053171095Ssam * @is_tcp: Set to 1, if the protocol is TCP. 6054173139Srwatson * 0, if the protocol is UDP. 6055171095Ssam * @is_ipv4: Set to 1, if the protocol is IPv4. 6056173139Srwatson * 0, if the protocol is IPv6. 6057171095Ssam * @tgt_queue: Target queue to route the receive packet. 6058171095Ssam * 6059171095Ssam * This function add a new entry to the SPDM table. 6060171095Ssam * 6061171095Ssam * Returns: XGE_HAL_OK - success. 6062171095Ssam * XGE_HAL_ERR_SPDM_NOT_ENABLED - SPDM support is not enabled. 6063171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to add a new entry with in 6064173139Srwatson * the time(timeout). 6065171095Ssam * XGE_HAL_ERR_SPDM_TABLE_FULL - SPDM table is full. 6066171095Ssam * XGE_HAL_ERR_SPDM_INVALID_ENTRY - Invalid SPDM entry. 6067171095Ssam * 6068171095Ssam * See also: xge_hal_spdm_entry_remove{}. 6069171095Ssam */ 6070171095Ssamxge_hal_status_e 6071171095Ssamxge_hal_spdm_entry_add(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, 6072173139Srwatson xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, 6073173139Srwatson u8 is_tcp, u8 is_ipv4, u8 tgt_queue) 6074171095Ssam{ 6075171095Ssam 6076171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 6077171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6078171095Ssam u32 jhash_value; 6079171095Ssam u32 jhash_init_val; 6080171095Ssam u32 jhash_golden_ratio; 6081171095Ssam u64 val64; 6082171095Ssam int off; 6083171095Ssam u16 spdm_entry; 6084171095Ssam u8 msg[XGE_HAL_JHASH_MSG_LEN]; 6085171095Ssam int ipaddr_len; 6086171095Ssam xge_hal_status_e status; 6087171095Ssam 6088171095Ssam 6089171095Ssam if (!hldev->config.rth_spdm_en) { 6090173139Srwatson return XGE_HAL_ERR_SPDM_NOT_ENABLED; 6091171095Ssam } 6092171095Ssam 6093171095Ssam if ((tgt_queue < XGE_HAL_MIN_RING_NUM) || 6094173139Srwatson (tgt_queue > XGE_HAL_MAX_RING_NUM)) { 6095173139Srwatson return XGE_HAL_ERR_SPDM_INVALID_ENTRY; 6096171095Ssam } 6097171095Ssam 6098171095Ssam 6099171095Ssam /* 6100171095Ssam * Calculate the jenkins hash. 6101171095Ssam */ 6102171095Ssam /* 6103171095Ssam * Create the Jenkins hash algorithm key. 6104171095Ssam * key = {L3SA, L3DA, L4SP, L4DP}, if SPDM is configured to 6105171095Ssam * use L4 information. Otherwize key = {L3SA, L3DA}. 6106171095Ssam */ 6107171095Ssam 6108171095Ssam if (is_ipv4) { 6109173139Srwatson ipaddr_len = 4; // In bytes 6110171095Ssam } else { 6111173139Srwatson ipaddr_len = 16; 6112171095Ssam } 6113171095Ssam 6114171095Ssam /* 6115171095Ssam * Jenkins hash algorithm expects the key in the big endian 6116171095Ssam * format. Since key is the byte array, memcpy won't work in the 6117171095Ssam * case of little endian. So, the current code extracts each 6118171095Ssam * byte starting from MSB and store it in the key. 6119171095Ssam */ 6120171095Ssam if (is_ipv4) { 6121173139Srwatson for (off = 0; off < ipaddr_len; off++) { 6122173139Srwatson u32 mask = vBIT32(0xff,(off*8),8); 6123173139Srwatson int shift = 32-(off+1)*8; 6124173139Srwatson msg[off] = (u8)((src_ip->ipv4.addr & mask) >> shift); 6125173139Srwatson msg[off+ipaddr_len] = 6126173139Srwatson (u8)((dst_ip->ipv4.addr & mask) >> shift); 6127173139Srwatson } 6128171095Ssam } else { 6129173139Srwatson for (off = 0; off < ipaddr_len; off++) { 6130173139Srwatson int loc = off % 8; 6131173139Srwatson u64 mask = vBIT(0xff,(loc*8),8); 6132173139Srwatson int shift = 64-(loc+1)*8; 6133171095Ssam 6134173139Srwatson msg[off] = (u8)((src_ip->ipv6.addr[off/8] & mask) 6135173139Srwatson >> shift); 6136173139Srwatson msg[off+ipaddr_len] = (u8)((dst_ip->ipv6.addr[off/8] 6137173139Srwatson & mask) >> shift); 6138173139Srwatson } 6139171095Ssam } 6140171095Ssam 6141171095Ssam off = (2*ipaddr_len); 6142171095Ssam 6143171095Ssam if (hldev->config.rth_spdm_use_l4) { 6144173139Srwatson msg[off] = (u8)((l4_sp & 0xff00) >> 8); 6145173139Srwatson msg[off + 1] = (u8)(l4_sp & 0xff); 6146173139Srwatson msg[off + 2] = (u8)((l4_dp & 0xff00) >> 8); 6147173139Srwatson msg[off + 3] = (u8)(l4_dp & 0xff); 6148173139Srwatson off += 4; 6149171095Ssam } 6150171095Ssam 6151171095Ssam /* 6152171095Ssam * Calculate jenkins hash for this configuration 6153171095Ssam */ 6154171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, 6155173139Srwatson hldev->regh0, 6156173139Srwatson &bar0->rts_rth_jhash_cfg); 6157171095Ssam jhash_golden_ratio = (u32)(val64 >> 32); 6158171095Ssam jhash_init_val = (u32)(val64 & 0xffffffff); 6159171095Ssam 6160171095Ssam jhash_value = __hal_calc_jhash(msg, off, 6161173139Srwatson jhash_golden_ratio, 6162173139Srwatson jhash_init_val); 6163171095Ssam 6164171095Ssam xge_os_spin_lock(&hldev->spdm_lock); 6165171095Ssam 6166171095Ssam /* 6167171095Ssam * Locate a free slot in the SPDM table. To avoid a seach in the 6168171095Ssam * actual SPDM table, which is very expensive in terms of time, 6169171095Ssam * we are maintaining a local copy of the table and the search for 6170171095Ssam * the free entry is performed in the local table. 6171171095Ssam */ 6172171095Ssam if ((status = __hal_get_free_spdm_entry(hldev,&spdm_entry)) 6173173139Srwatson != XGE_HAL_OK) { 6174173139Srwatson xge_os_spin_unlock(&hldev->spdm_lock); 6175173139Srwatson return status; 6176171095Ssam } 6177171095Ssam 6178171095Ssam /* 6179171095Ssam * Add this entry to the SPDM table 6180171095Ssam */ 6181171095Ssam status = __hal_spdm_entry_add(hldev, src_ip, dst_ip, l4_sp, l4_dp, 6182173139Srwatson is_tcp, is_ipv4, tgt_queue, 6183173139Srwatson jhash_value, /* calculated jhash */ 6184173139Srwatson spdm_entry); 6185171095Ssam 6186171095Ssam xge_os_spin_unlock(&hldev->spdm_lock); 6187171095Ssam 6188171095Ssam return status; 6189171095Ssam} 6190171095Ssam 6191171095Ssam/** 6192171095Ssam * xge_hal_spdm_entry_remove - Remove an entry from the SPDM table. 6193171095Ssam * @devh: HAL device handle. 6194171095Ssam * @src_ip: Source ip address(IPv4/IPv6). 6195171095Ssam * @dst_ip: Destination ip address(IPv4/IPv6). 6196171095Ssam * @l4_sp: L4 source port. 6197171095Ssam * @l4_dp: L4 destination port. 6198171095Ssam * @is_tcp: Set to 1, if the protocol is TCP. 6199173139Srwatson * 0, if the protocol os UDP. 6200171095Ssam * @is_ipv4: Set to 1, if the protocol is IPv4. 6201173139Srwatson * 0, if the protocol is IPv6. 6202171095Ssam * 6203171095Ssam * This function remove an entry from the SPDM table. 6204171095Ssam * 6205171095Ssam * Returns: XGE_HAL_OK - success. 6206171095Ssam * XGE_HAL_ERR_SPDM_NOT_ENABLED - SPDM support is not enabled. 6207171095Ssam * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to remove an entry with in 6208173139Srwatson * the time(timeout). 6209171095Ssam * XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND - Unable to locate the entry in the SPDM 6210173139Srwatson * table. 6211171095Ssam * 6212171095Ssam * See also: xge_hal_spdm_entry_add{}. 6213171095Ssam */ 6214171095Ssamxge_hal_status_e 6215171095Ssamxge_hal_spdm_entry_remove(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, 6216173139Srwatson xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, 6217173139Srwatson u8 is_tcp, u8 is_ipv4) 6218171095Ssam{ 6219171095Ssam 6220171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 6221171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6222171095Ssam u64 val64; 6223171095Ssam u16 spdm_entry; 6224171095Ssam xge_hal_status_e status; 6225171095Ssam u64 spdm_line_arr[8]; 6226171095Ssam u8 line_no; 6227171095Ssam u8 spdm_is_tcp; 6228171095Ssam u8 spdm_is_ipv4; 6229171095Ssam u16 spdm_l4_sp; 6230171095Ssam u16 spdm_l4_dp; 6231171095Ssam 6232171095Ssam if (!hldev->config.rth_spdm_en) { 6233173139Srwatson return XGE_HAL_ERR_SPDM_NOT_ENABLED; 6234171095Ssam } 6235171095Ssam 6236171095Ssam xge_os_spin_lock(&hldev->spdm_lock); 6237171095Ssam 6238171095Ssam /* 6239171095Ssam * Poll the rxpic_int_reg register until spdm ready bit is set or 6240171095Ssam * timeout happens. 6241171095Ssam */ 6242171095Ssam if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1, 6243173139Srwatson XGE_HAL_RX_PIC_INT_REG_SPDM_READY, 6244173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 6245171095Ssam 6246173139Srwatson /* upper layer may require to repeat */ 6247173139Srwatson xge_os_spin_unlock(&hldev->spdm_lock); 6248173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 6249171095Ssam } 6250171095Ssam 6251171095Ssam /* 6252171095Ssam * Clear the SPDM READY bit. 6253171095Ssam */ 6254171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6255173139Srwatson &bar0->rxpic_int_reg); 6256171095Ssam val64 &= ~XGE_HAL_RX_PIC_INT_REG_SPDM_READY; 6257171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6258173139Srwatson &bar0->rxpic_int_reg); 6259171095Ssam 6260171095Ssam /* 6261171095Ssam * Search in the local SPDM table to get the index of the 6262171095Ssam * corresponding entry in the SPDM table. 6263171095Ssam */ 6264171095Ssam spdm_entry = 0; 6265171095Ssam for (;spdm_entry < hldev->spdm_max_entries; spdm_entry++) { 6266173139Srwatson if ((!hldev->spdm_table[spdm_entry]->in_use) || 6267173139Srwatson (hldev->spdm_table[spdm_entry]->is_tcp != is_tcp) || 6268173139Srwatson (hldev->spdm_table[spdm_entry]->l4_sp != l4_sp) || 6269173139Srwatson (hldev->spdm_table[spdm_entry]->l4_dp != l4_dp) || 6270173139Srwatson (hldev->spdm_table[spdm_entry]->is_ipv4 != is_ipv4)) { 6271173139Srwatson continue; 6272173139Srwatson } 6273171095Ssam 6274173139Srwatson /* 6275173139Srwatson * Compare the src/dst IP addresses of source and target 6276173139Srwatson */ 6277173139Srwatson if (is_ipv4) { 6278173139Srwatson if ((hldev->spdm_table[spdm_entry]->src_ip.ipv4.addr 6279173139Srwatson != src_ip->ipv4.addr) || 6280173139Srwatson (hldev->spdm_table[spdm_entry]->dst_ip.ipv4.addr 6281173139Srwatson != dst_ip->ipv4.addr)) { 6282173139Srwatson continue; 6283173139Srwatson } 6284173139Srwatson } else { 6285173139Srwatson if ((hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[0] 6286173139Srwatson != src_ip->ipv6.addr[0]) || 6287173139Srwatson (hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[1] 6288173139Srwatson != src_ip->ipv6.addr[1]) || 6289173139Srwatson (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[0] 6290173139Srwatson != dst_ip->ipv6.addr[0]) || 6291173139Srwatson (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[1] 6292173139Srwatson != dst_ip->ipv6.addr[1])) { 6293173139Srwatson continue; 6294173139Srwatson } 6295173139Srwatson } 6296173139Srwatson break; 6297171095Ssam } 6298171095Ssam 6299171095Ssam if (spdm_entry >= hldev->spdm_max_entries) { 6300173139Srwatson xge_os_spin_unlock(&hldev->spdm_lock); 6301173139Srwatson return XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND; 6302171095Ssam } 6303171095Ssam 6304171095Ssam /* 6305171095Ssam * Retrieve the corresponding entry from the SPDM table and 6306171095Ssam * make sure that the data is consistent. 6307171095Ssam */ 6308171095Ssam for(line_no = 0; line_no < 8; line_no++) { 6309171095Ssam 6310173139Srwatson /* 6311173139Srwatson * SPDM line 2,3,4 are valid only for IPv6 entry. 6312173139Srwatson * SPDM line 5 & 6 are reserved. We don't have to 6313173139Srwatson * read these entries in the above cases. 6314173139Srwatson */ 6315173139Srwatson if (((is_ipv4) && 6316173139Srwatson ((line_no == 2)||(line_no == 3)||(line_no == 4))) || 6317173139Srwatson (line_no == 5) || 6318173139Srwatson (line_no == 6)) { 6319173139Srwatson continue; 6320173139Srwatson } 6321171095Ssam 6322173139Srwatson if ((status = __hal_read_spdm_entry_line( 6323173139Srwatson hldev, 6324173139Srwatson line_no, 6325173139Srwatson spdm_entry, 6326173139Srwatson &spdm_line_arr[line_no])) 6327173139Srwatson != XGE_HAL_OK) { 6328173139Srwatson xge_os_spin_unlock(&hldev->spdm_lock); 6329173139Srwatson return status; 6330173139Srwatson } 6331171095Ssam } 6332171095Ssam 6333171095Ssam /* 6334171095Ssam * Seventh line of the spdm entry contains the entry_enable 6335171095Ssam * bit. Make sure that the entry_enable bit of this spdm entry 6336171095Ssam * is set. 6337171095Ssam * To remove an entry from the SPDM table, reset this 6338171095Ssam * bit. 6339171095Ssam */ 6340171095Ssam if (!(spdm_line_arr[7] & BIT(63))) { 6341173139Srwatson /* 6342173139Srwatson * Log a warning 6343173139Srwatson */ 6344173139Srwatson xge_debug_device(XGE_ERR, "Local SPDM table is not " 6345173139Srwatson "consistent with the actual one for the spdm " 6346173139Srwatson "entry %d ", spdm_entry); 6347173139Srwatson goto err_exit; 6348171095Ssam } 6349171095Ssam 6350171095Ssam /* 6351171095Ssam * Retreive the L4 SP/DP, src/dst ip addresses from the SPDM 6352171095Ssam * table and do a comparision. 6353171095Ssam */ 6354171095Ssam spdm_is_tcp = (u8)((spdm_line_arr[0] & BIT(59)) >> 4); 6355171095Ssam spdm_is_ipv4 = (u8)(spdm_line_arr[0] & BIT(63)); 6356171095Ssam spdm_l4_sp = (u16)(spdm_line_arr[0] >> 48); 6357171095Ssam spdm_l4_dp = (u16)((spdm_line_arr[0] >> 32) & 0xffff); 6358171095Ssam 6359171095Ssam 6360171095Ssam if ((spdm_is_tcp != is_tcp) || 6361171095Ssam (spdm_is_ipv4 != is_ipv4) || 6362171095Ssam (spdm_l4_sp != l4_sp) || 6363171095Ssam (spdm_l4_dp != l4_dp)) { 6364173139Srwatson /* 6365173139Srwatson * Log a warning 6366173139Srwatson */ 6367173139Srwatson xge_debug_device(XGE_ERR, "Local SPDM table is not " 6368173139Srwatson "consistent with the actual one for the spdm " 6369173139Srwatson "entry %d ", spdm_entry); 6370173139Srwatson goto err_exit; 6371171095Ssam } 6372171095Ssam 6373171095Ssam if (is_ipv4) { 6374173139Srwatson /* Upper 32 bits of spdm_line(64 bit) contains the 6375173139Srwatson * src IPv4 address. Lower 32 bits of spdm_line 6376173139Srwatson * contains the destination IPv4 address. 6377173139Srwatson */ 6378173139Srwatson u32 temp_src_ip = (u32)(spdm_line_arr[1] >> 32); 6379173139Srwatson u32 temp_dst_ip = (u32)(spdm_line_arr[1] & 0xffffffff); 6380171095Ssam 6381173139Srwatson if ((temp_src_ip != src_ip->ipv4.addr) || 6382173139Srwatson (temp_dst_ip != dst_ip->ipv4.addr)) { 6383173139Srwatson xge_debug_device(XGE_ERR, "Local SPDM table is not " 6384173139Srwatson "consistent with the actual one for the spdm " 6385173139Srwatson "entry %d ", spdm_entry); 6386173139Srwatson goto err_exit; 6387173139Srwatson } 6388171095Ssam 6389171095Ssam } else { 6390173139Srwatson /* 6391173139Srwatson * SPDM line 1 & 2 contains the src IPv6 address. 6392173139Srwatson * SPDM line 3 & 4 contains the dst IPv6 address. 6393173139Srwatson */ 6394173139Srwatson if ((spdm_line_arr[1] != src_ip->ipv6.addr[0]) || 6395173139Srwatson (spdm_line_arr[2] != src_ip->ipv6.addr[1]) || 6396173139Srwatson (spdm_line_arr[3] != dst_ip->ipv6.addr[0]) || 6397173139Srwatson (spdm_line_arr[4] != dst_ip->ipv6.addr[1])) { 6398171095Ssam 6399173139Srwatson /* 6400173139Srwatson * Log a warning 6401173139Srwatson */ 6402173139Srwatson xge_debug_device(XGE_ERR, "Local SPDM table is not " 6403173139Srwatson "consistent with the actual one for the spdm " 6404173139Srwatson "entry %d ", spdm_entry); 6405173139Srwatson goto err_exit; 6406173139Srwatson } 6407171095Ssam } 6408171095Ssam 6409171095Ssam /* 6410171095Ssam * Reset the entry_enable bit to zero 6411171095Ssam */ 6412171095Ssam spdm_line_arr[7] &= ~BIT(63); 6413171095Ssam 6414171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6415173139Srwatson spdm_line_arr[7], 6416173139Srwatson (void *)((char *)hldev->spdm_mem_base + 6417173139Srwatson (spdm_entry * 64) + (7 * 8))); 6418171095Ssam 6419171095Ssam /* 6420171095Ssam * Wait for the operation to be completed. 6421171095Ssam */ 6422171095Ssam if (__hal_device_register_poll(hldev, 6423173139Srwatson &bar0->rxpic_int_reg, 1, 6424173139Srwatson XGE_HAL_RX_PIC_INT_REG_SPDM_READY, 6425173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 6426173139Srwatson xge_os_spin_unlock(&hldev->spdm_lock); 6427173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 6428171095Ssam } 6429171095Ssam 6430171095Ssam /* 6431171095Ssam * Make the corresponding spdm entry in the local SPDM table 6432171095Ssam * available for future use. 6433171095Ssam */ 6434171095Ssam hldev->spdm_table[spdm_entry]->in_use = 0; 6435171095Ssam xge_os_spin_unlock(&hldev->spdm_lock); 6436171095Ssam 6437171095Ssam return XGE_HAL_OK; 6438171095Ssam 6439171095Ssamerr_exit: 6440171095Ssam xge_os_spin_unlock(&hldev->spdm_lock); 6441171095Ssam return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT; 6442171095Ssam} 6443171095Ssam 6444171095Ssam/* 6445171095Ssam * __hal_device_rti_set 6446171095Ssam * @ring: The post_qid of the ring. 6447171095Ssam * @channel: HAL channel of the ring. 6448171095Ssam * 6449171095Ssam * This function stores the RTI value associated for the MSI and 6450171095Ssam * also unmasks this particular RTI in the rti_mask register. 6451171095Ssam */ 6452171095Ssamstatic void __hal_device_rti_set(int ring_qid, xge_hal_channel_t *channel) 6453171095Ssam{ 6454171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6455171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6456171095Ssam u64 val64; 6457171095Ssam 6458171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || 6459171095Ssam hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) 6460173139Srwatson channel->rti = (u8)ring_qid; 6461171095Ssam 6462171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6463173139Srwatson &bar0->rx_traffic_mask); 6464171095Ssam val64 &= ~BIT(ring_qid); 6465171095Ssam xge_os_pio_mem_write64(hldev->pdev, 6466173139Srwatson hldev->regh0, val64, 6467173139Srwatson &bar0->rx_traffic_mask); 6468171095Ssam} 6469171095Ssam 6470171095Ssam/* 6471171095Ssam * __hal_device_tti_set 6472171095Ssam * @ring: The post_qid of the FIFO. 6473171095Ssam * @channel: HAL channel the FIFO. 6474171095Ssam * 6475171095Ssam * This function stores the TTI value associated for the MSI and 6476171095Ssam * also unmasks this particular TTI in the tti_mask register. 6477171095Ssam */ 6478171095Ssamstatic void __hal_device_tti_set(int fifo_qid, xge_hal_channel_t *channel) 6479171095Ssam{ 6480171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6481171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6482171095Ssam u64 val64; 6483171095Ssam 6484171095Ssam if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || 6485171095Ssam hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) 6486173139Srwatson channel->tti = (u8)fifo_qid; 6487171095Ssam 6488171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6489173139Srwatson &bar0->tx_traffic_mask); 6490171095Ssam val64 &= ~BIT(fifo_qid); 6491171095Ssam xge_os_pio_mem_write64(hldev->pdev, 6492173139Srwatson hldev->regh0, val64, 6493173139Srwatson &bar0->tx_traffic_mask); 6494171095Ssam} 6495171095Ssam 6496171095Ssam/** 6497171095Ssam * xge_hal_channel_msi_set - Associate a RTI with a ring or TTI with a 6498171095Ssam * FIFO for a given MSI. 6499171095Ssam * @channelh: HAL channel handle. 6500171095Ssam * @msi: MSI Number associated with the channel. 6501171095Ssam * @msi_msg: The MSI message associated with the MSI number above. 6502171095Ssam * 6503171095Ssam * This API will associate a given channel (either Ring or FIFO) with the 6504171095Ssam * given MSI number. It will alo program the Tx_Mat/Rx_Mat tables in the 6505171095Ssam * hardware to indicate this association to the hardware. 6506171095Ssam */ 6507171095Ssamxge_hal_status_e 6508171095Ssamxge_hal_channel_msi_set(xge_hal_channel_h channelh, int msi, u32 msi_msg) 6509171095Ssam{ 6510171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 6511171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6512171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6513171095Ssam u64 val64; 6514171095Ssam 6515171095Ssam channel->msi_msg = msi_msg; 6516171095Ssam if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 6517173139Srwatson int ring = channel->post_qid; 6518173139Srwatson xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Ring: %d," 6519173139Srwatson " MSI: %d", channel->msi_msg, ring, msi); 6520173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6521173139Srwatson &bar0->rx_mat); 6522173139Srwatson val64 |= XGE_HAL_SET_RX_MAT(ring, msi); 6523173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6524173139Srwatson &bar0->rx_mat); 6525173139Srwatson __hal_device_rti_set(ring, channel); 6526171095Ssam } else { 6527173139Srwatson int fifo = channel->post_qid; 6528173139Srwatson xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Fifo: %d," 6529173139Srwatson " MSI: %d", channel->msi_msg, fifo, msi); 6530173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6531173139Srwatson &bar0->tx_mat[0]); 6532173139Srwatson val64 |= XGE_HAL_SET_TX_MAT(fifo, msi); 6533173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6534173139Srwatson &bar0->tx_mat[0]); 6535173139Srwatson __hal_device_tti_set(fifo, channel); 6536171095Ssam } 6537171095Ssam 6538171095Ssam return XGE_HAL_OK; 6539171095Ssam} 6540171095Ssam 6541171095Ssam/** 6542171095Ssam * xge_hal_mask_msix - Begin IRQ processing. 6543171095Ssam * @hldev: HAL device handle. 6544171095Ssam * @msi_id: MSI ID 6545171095Ssam * 6546171095Ssam * The function masks the msix interrupt for the given msi_id 6547171095Ssam * 6548171095Ssam * Note: 6549171095Ssam * 6550171095Ssam * Returns: 0, 6551171095Ssam * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range 6552171095Ssam * status. 6553171095Ssam * See also: 6554171095Ssam */ 6555171095Ssamxge_hal_status_e 6556171095Ssamxge_hal_mask_msix(xge_hal_device_h devh, int msi_id) 6557171095Ssam{ 6558171095Ssam xge_hal_status_e status = XGE_HAL_OK; 6559171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 6560171095Ssam u32 *bar2 = (u32 *)hldev->bar2; 6561171095Ssam u32 val32; 6562171095Ssam 6563171095Ssam xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES); 6564171095Ssam 6565171095Ssam val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]); 6566171095Ssam val32 |= 1; 6567171095Ssam xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]); 6568171095Ssam return status; 6569171095Ssam} 6570171095Ssam 6571171095Ssam/** 6572171095Ssam * xge_hal_mask_msix - Begin IRQ processing. 6573171095Ssam * @hldev: HAL device handle. 6574171095Ssam * @msi_id: MSI ID 6575171095Ssam * 6576171095Ssam * The function masks the msix interrupt for the given msi_id 6577171095Ssam * 6578171095Ssam * Note: 6579171095Ssam * 6580171095Ssam * Returns: 0, 6581171095Ssam * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range 6582171095Ssam * status. 6583171095Ssam * See also: 6584171095Ssam */ 6585171095Ssamxge_hal_status_e 6586171095Ssamxge_hal_unmask_msix(xge_hal_device_h devh, int msi_id) 6587171095Ssam{ 6588171095Ssam xge_hal_status_e status = XGE_HAL_OK; 6589171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 6590171095Ssam u32 *bar2 = (u32 *)hldev->bar2; 6591171095Ssam u32 val32; 6592171095Ssam 6593171095Ssam xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES); 6594171095Ssam 6595171095Ssam val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]); 6596171095Ssam val32 &= ~1; 6597171095Ssam xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]); 6598171095Ssam return status; 6599171095Ssam} 6600171095Ssam 6601171095Ssam/* 6602171095Ssam * __hal_set_msix_vals 6603171095Ssam * @devh: HAL device handle. 6604171095Ssam * @msix_value: 32bit MSI-X value transferred across PCI to @msix_address. 6605171095Ssam * Filled in by this function. 6606171095Ssam * @msix_address: 32bit MSI-X DMA address. 6607171095Ssam * Filled in by this function. 6608171095Ssam * @msix_idx: index that corresponds to the (@msix_value, @msix_address) 6609171095Ssam * entry in the table of MSI-X (value, address) pairs. 6610171095Ssam * 6611171095Ssam * This function will program the hardware associating the given 6612171095Ssam * address/value cobination to the specified msi number. 6613171095Ssam */ 6614171095Ssamstatic void __hal_set_msix_vals (xge_hal_device_h devh, 6615173139Srwatson u32 *msix_value, 6616173139Srwatson u64 *msix_addr, 6617173139Srwatson int msix_idx) 6618171095Ssam{ 6619171095Ssam int cnt = 0; 6620171095Ssam 6621171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 6622171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6623171095Ssam u64 val64; 6624171095Ssam 6625171095Ssam val64 = XGE_HAL_XMSI_NO(msix_idx) | XGE_HAL_XMSI_STROBE; 6626171095Ssam __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 6627173139Srwatson (u32)(val64 >> 32), &bar0->xmsi_access); 6628171095Ssam __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, 6629173139Srwatson (u32)(val64), &bar0->xmsi_access); 6630171095Ssam do { 6631173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6632173139Srwatson &bar0->xmsi_access); 6633173139Srwatson if (val64 & XGE_HAL_XMSI_STROBE) 6634173139Srwatson break; 6635173139Srwatson cnt++; 6636173139Srwatson xge_os_mdelay(20); 6637171095Ssam } while(cnt < 5); 6638171095Ssam *msix_value = (u32)(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6639173139Srwatson &bar0->xmsi_data)); 6640171095Ssam *msix_addr = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6641173139Srwatson &bar0->xmsi_address); 6642171095Ssam} 6643171095Ssam 6644171095Ssam/** 6645171095Ssam * xge_hal_channel_msix_set - Associate MSI-X with a channel. 6646171095Ssam * @channelh: HAL channel handle. 6647171095Ssam * @msix_idx: index that corresponds to a particular (@msix_value, 6648171095Ssam * @msix_address) entry in the MSI-X table. 6649171095Ssam * 6650171095Ssam * This API associates a given channel (either Ring or FIFO) with the 6651171095Ssam * given MSI-X number. It programs the Xframe's Tx_Mat/Rx_Mat tables 6652171095Ssam * to indicate this association. 6653171095Ssam */ 6654171095Ssamxge_hal_status_e 6655171095Ssamxge_hal_channel_msix_set(xge_hal_channel_h channelh, int msix_idx) 6656171095Ssam{ 6657171095Ssam xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 6658171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6659171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6660171095Ssam u64 val64; 6661171095Ssam 6662171095Ssam if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 6663173139Srwatson /* Currently Ring and RTI is one on one. */ 6664173139Srwatson int ring = channel->post_qid; 6665173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6666173139Srwatson &bar0->rx_mat); 6667173139Srwatson val64 |= XGE_HAL_SET_RX_MAT(ring, msix_idx); 6668173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6669173139Srwatson &bar0->rx_mat); 6670173139Srwatson __hal_device_rti_set(ring, channel); 6671173139Srwatson hldev->config.fifo.queue[channel->post_qid].intr_vector = 6672173139Srwatson msix_idx; 6673171095Ssam } else if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 6674173139Srwatson int fifo = channel->post_qid; 6675173139Srwatson val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6676173139Srwatson &bar0->tx_mat[0]); 6677173139Srwatson val64 |= XGE_HAL_SET_TX_MAT(fifo, msix_idx); 6678173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6679173139Srwatson &bar0->tx_mat[0]); 6680173139Srwatson __hal_device_tti_set(fifo, channel); 6681173139Srwatson hldev->config.ring.queue[channel->post_qid].intr_vector = 6682173139Srwatson msix_idx; 6683171095Ssam } 6684171095Ssam channel->msix_idx = msix_idx; 6685171095Ssam __hal_set_msix_vals(hldev, &channel->msix_data, 6686173139Srwatson &channel->msix_address, 6687173139Srwatson channel->msix_idx); 6688171095Ssam 6689171095Ssam return XGE_HAL_OK; 6690171095Ssam} 6691171095Ssam 6692171095Ssam#if defined(XGE_HAL_CONFIG_LRO) 6693171095Ssam/** 6694171095Ssam * xge_hal_lro_terminate - Terminate lro resources. 6695171095Ssam * @lro_scale: Amount of lro memory. 6696171095Ssam * @hldev: Hal device structure. 6697171095Ssam * 6698171095Ssam */ 6699171095Ssamvoid 6700171095Ssamxge_hal_lro_terminate(u32 lro_scale, 6701171095Ssam xge_hal_device_t *hldev) 6702171095Ssam{ 6703171095Ssam} 6704171095Ssam 6705171095Ssam/** 6706171095Ssam * xge_hal_lro_init - Initiate lro resources. 6707171095Ssam * @lro_scale: Amount of lro memory. 6708171095Ssam * @hldev: Hal device structure. 6709171095Ssam * Note: For time being I am using only one LRO per device. Later on size 6710171095Ssam * will be increased. 6711171095Ssam */ 6712171095Ssam 6713171095Ssamxge_hal_status_e 6714171095Ssamxge_hal_lro_init(u32 lro_scale, 6715171095Ssam xge_hal_device_t *hldev) 6716171095Ssam{ 6717171095Ssam int i; 6718171095Ssam 6719171095Ssam if (hldev->config.lro_sg_size == XGE_HAL_DEFAULT_USE_HARDCODE) 6720173139Srwatson hldev->config.lro_sg_size = XGE_HAL_LRO_DEFAULT_SG_SIZE; 6721171095Ssam 6722171095Ssam if (hldev->config.lro_frm_len == XGE_HAL_DEFAULT_USE_HARDCODE) 6723173139Srwatson hldev->config.lro_frm_len = XGE_HAL_LRO_DEFAULT_FRM_LEN; 6724171095Ssam 6725171095Ssam for (i=0; i < XGE_HAL_MAX_RING_NUM; i++) 6726171095Ssam { 6727173139Srwatson xge_os_memzero(hldev->lro_desc[i].lro_pool, 6728173139Srwatson sizeof(lro_t) * XGE_HAL_LRO_MAX_BUCKETS); 6729171095Ssam 6730173139Srwatson hldev->lro_desc[i].lro_next_idx = 0; 6731173139Srwatson hldev->lro_desc[i].lro_recent = NULL; 6732171095Ssam } 6733171095Ssam 6734171095Ssam return XGE_HAL_OK; 6735171095Ssam} 6736171095Ssam#endif 6737171095Ssam 6738171095Ssam 6739171095Ssam/** 6740171095Ssam * xge_hal_device_poll - HAL device "polling" entry point. 6741171095Ssam * @devh: HAL device. 6742171095Ssam * 6743171095Ssam * HAL "polling" entry point. Note that this is part of HAL public API. 6744171095Ssam * Upper-Layer driver _must_ periodically poll HAL via 6745171095Ssam * xge_hal_device_poll(). 6746171095Ssam * 6747171095Ssam * HAL uses caller's execution context to serially process accumulated 6748171095Ssam * slow-path events, such as link state changes and hardware error 6749171095Ssam * indications. 6750171095Ssam * 6751171095Ssam * The rate of polling could be somewhere between 500us to 10ms, 6752171095Ssam * depending on requirements (e.g., the requirement to support fail-over 6753171095Ssam * could mean that 500us or even 100us polling interval need to be used). 6754171095Ssam * 6755171095Ssam * The need and motivation for external polling includes 6756171095Ssam * 6757171095Ssam * - remove the error-checking "burden" from the HAL interrupt handler 6758171095Ssam * (see xge_hal_device_handle_irq()); 6759171095Ssam * 6760171095Ssam * - remove the potential source of portability issues by _not_ 6761171095Ssam * implementing separate polling thread within HAL itself. 6762171095Ssam * 6763171095Ssam * See also: xge_hal_event_e{}, xge_hal_driver_config_t{}. 6764171095Ssam * Usage: See ex_slow_path{}. 6765171095Ssam */ 6766171095Ssamvoid 6767171095Ssamxge_hal_device_poll(xge_hal_device_h devh) 6768171095Ssam{ 6769171095Ssam unsigned char item_buf[sizeof(xge_queue_item_t) + 6770173139Srwatson XGE_DEFAULT_EVENT_MAX_DATA_SIZE]; 6771171095Ssam xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf; 6772171095Ssam xge_queue_status_e qstatus; 6773171095Ssam xge_hal_status_e hstatus; 6774171095Ssam int i = 0; 6775171095Ssam int queue_has_critical_event = 0; 6776171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 6777171095Ssam 6778171095Ssam xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) + 6779173139Srwatson XGE_DEFAULT_EVENT_MAX_DATA_SIZE)); 6780171095Ssam 6781171095Ssam_again: 6782171095Ssam if (!hldev->is_initialized || 6783171095Ssam hldev->terminating || 6784171095Ssam hldev->magic != XGE_HAL_MAGIC) 6785173139Srwatson return; 6786171095Ssam 6787171095Ssam if(hldev->stats.sw_dev_err_stats.xpak_counter.tick_period < 72000) 6788171095Ssam { 6789173139Srwatson /* 6790173139Srwatson * Wait for an Hour 6791173139Srwatson */ 6792173139Srwatson hldev->stats.sw_dev_err_stats.xpak_counter.tick_period++; 6793171095Ssam } else { 6794173139Srwatson /* 6795173139Srwatson * Logging Error messages in the excess temperature, 6796173139Srwatson * Bias current, laser ouput for three cycle 6797173139Srwatson */ 6798173139Srwatson __hal_updt_stats_xpak(hldev); 6799173139Srwatson hldev->stats.sw_dev_err_stats.xpak_counter.tick_period = 0; 6800171095Ssam } 6801171095Ssam 6802171095Ssam if (!queue_has_critical_event) 6803171095Ssam queue_has_critical_event = 6804173139Srwatson __queue_get_reset_critical(hldev->queueh); 6805171095Ssam 6806171095Ssam hldev->in_poll = 1; 6807171095Ssam while (i++ < XGE_HAL_DRIVER_QUEUE_CONSUME_MAX || queue_has_critical_event) { 6808171095Ssam 6809173139Srwatson qstatus = xge_queue_consume(hldev->queueh, 6810173139Srwatson XGE_DEFAULT_EVENT_MAX_DATA_SIZE, 6811173139Srwatson item); 6812173139Srwatson if (qstatus == XGE_QUEUE_IS_EMPTY) 6813173139Srwatson break; 6814171095Ssam 6815173139Srwatson xge_debug_queue(XGE_TRACE, 6816173139Srwatson "queueh 0x"XGE_OS_LLXFMT" consumed event: %d ctxt 0x" 6817173139Srwatson XGE_OS_LLXFMT, (u64)(ulong_t)hldev->queueh, item->event_type, 6818173139Srwatson (u64)(ulong_t)item->context); 6819171095Ssam 6820173139Srwatson if (!hldev->is_initialized || 6821173139Srwatson hldev->magic != XGE_HAL_MAGIC) { 6822173139Srwatson hldev->in_poll = 0; 6823173139Srwatson return; 6824173139Srwatson } 6825171095Ssam 6826173139Srwatson switch (item->event_type) { 6827173139Srwatson case XGE_HAL_EVENT_LINK_IS_UP: { 6828173139Srwatson if (!queue_has_critical_event && 6829173139Srwatson g_xge_hal_driver->uld_callbacks.link_up) { 6830173139Srwatson g_xge_hal_driver->uld_callbacks.link_up( 6831173139Srwatson hldev->upper_layer_info); 6832173139Srwatson hldev->link_state = XGE_HAL_LINK_UP; 6833173139Srwatson } 6834173139Srwatson } break; 6835173139Srwatson case XGE_HAL_EVENT_LINK_IS_DOWN: { 6836173139Srwatson if (!queue_has_critical_event && 6837173139Srwatson g_xge_hal_driver->uld_callbacks.link_down) { 6838173139Srwatson g_xge_hal_driver->uld_callbacks.link_down( 6839173139Srwatson hldev->upper_layer_info); 6840173139Srwatson hldev->link_state = XGE_HAL_LINK_DOWN; 6841173139Srwatson } 6842173139Srwatson } break; 6843173139Srwatson case XGE_HAL_EVENT_SERR: 6844173139Srwatson case XGE_HAL_EVENT_ECCERR: 6845173139Srwatson case XGE_HAL_EVENT_PARITYERR: 6846173139Srwatson case XGE_HAL_EVENT_TARGETABORT: 6847173139Srwatson case XGE_HAL_EVENT_SLOT_FREEZE: { 6848173139Srwatson void *item_data = xge_queue_item_data(item); 6849173139Srwatson xge_hal_event_e event_type = item->event_type; 6850173139Srwatson u64 val64 = *((u64*)item_data); 6851171095Ssam 6852173139Srwatson if (event_type != XGE_HAL_EVENT_SLOT_FREEZE) 6853173139Srwatson if (xge_hal_device_is_slot_freeze(hldev)) 6854173139Srwatson event_type = XGE_HAL_EVENT_SLOT_FREEZE; 6855173139Srwatson if (g_xge_hal_driver->uld_callbacks.crit_err) { 6856173139Srwatson g_xge_hal_driver->uld_callbacks.crit_err( 6857173139Srwatson hldev->upper_layer_info, 6858173139Srwatson event_type, 6859173139Srwatson val64); 6860173139Srwatson /* handle one critical event per poll cycle */ 6861173139Srwatson hldev->in_poll = 0; 6862173139Srwatson return; 6863173139Srwatson } 6864173139Srwatson } break; 6865173139Srwatson default: { 6866173139Srwatson xge_debug_queue(XGE_TRACE, 6867173139Srwatson "got non-HAL event %d", 6868173139Srwatson item->event_type); 6869173139Srwatson } break; 6870173139Srwatson } 6871171095Ssam 6872173139Srwatson /* broadcast this event */ 6873173139Srwatson if (g_xge_hal_driver->uld_callbacks.event) 6874173139Srwatson g_xge_hal_driver->uld_callbacks.event(item); 6875171095Ssam } 6876171095Ssam 6877171095Ssam if (g_xge_hal_driver->uld_callbacks.before_device_poll) { 6878173139Srwatson if (g_xge_hal_driver->uld_callbacks.before_device_poll( 6879173139Srwatson hldev) != 0) { 6880173139Srwatson hldev->in_poll = 0; 6881173139Srwatson return; 6882173139Srwatson } 6883171095Ssam } 6884171095Ssam 6885171095Ssam hstatus = __hal_device_poll(hldev); 6886171095Ssam if (g_xge_hal_driver->uld_callbacks.after_device_poll) 6887171095Ssam g_xge_hal_driver->uld_callbacks.after_device_poll(hldev); 6888171095Ssam 6889171095Ssam /* 6890171095Ssam * handle critical error right away: 6891171095Ssam * - walk the device queue again 6892171095Ssam * - drop non-critical events, if any 6893171095Ssam * - look for the 1st critical 6894171095Ssam */ 6895171095Ssam if (hstatus == XGE_HAL_ERR_CRITICAL) { 6896171095Ssam queue_has_critical_event = 1; 6897173139Srwatson goto _again; 6898171095Ssam } 6899171095Ssam 6900171095Ssam hldev->in_poll = 0; 6901171095Ssam} 6902171095Ssam 6903171095Ssam/** 6904171095Ssam * xge_hal_rts_rth_init - Set enhanced mode for RTS hashing. 6905171095Ssam * @hldev: HAL device handle. 6906171095Ssam * 6907171095Ssam * This function is used to set the adapter to enhanced mode. 6908171095Ssam * 6909171095Ssam * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). 6910171095Ssam */ 6911171095Ssamvoid 6912171095Ssamxge_hal_rts_rth_init(xge_hal_device_t *hldev) 6913171095Ssam{ 6914171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6915171095Ssam u64 val64; 6916171095Ssam 6917171095Ssam /* 6918171095Ssam * Set the receive traffic steering mode from default(classic) 6919171095Ssam * to enhanced. 6920171095Ssam */ 6921171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6922173139Srwatson &bar0->rts_ctrl); 6923171095Ssam val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 6924171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6925173139Srwatson val64, &bar0->rts_ctrl); 6926171095Ssam} 6927171095Ssam 6928171095Ssam/** 6929171095Ssam * xge_hal_rts_rth_clr - Clear RTS hashing. 6930171095Ssam * @hldev: HAL device handle. 6931171095Ssam * 6932171095Ssam * This function is used to clear all RTS hashing related stuff. 6933171095Ssam * It brings the adapter out from enhanced mode to classic mode. 6934171095Ssam * It also clears RTS_RTH_CFG register i.e clears hash type, function etc. 6935171095Ssam * 6936171095Ssam * See also: xge_hal_rts_rth_set(), xge_hal_rts_rth_itable_set(). 6937171095Ssam */ 6938171095Ssamvoid 6939171095Ssamxge_hal_rts_rth_clr(xge_hal_device_t *hldev) 6940171095Ssam{ 6941171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6942171095Ssam u64 val64; 6943171095Ssam 6944171095Ssam /* 6945171095Ssam * Set the receive traffic steering mode from default(classic) 6946171095Ssam * to enhanced. 6947171095Ssam */ 6948171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6949173139Srwatson &bar0->rts_ctrl); 6950171095Ssam val64 &= ~XGE_HAL_RTS_CTRL_ENHANCED_MODE; 6951171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6952173139Srwatson val64, &bar0->rts_ctrl); 6953171095Ssam val64 = 0; 6954171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6955173139Srwatson &bar0->rts_rth_cfg); 6956171095Ssam} 6957171095Ssam 6958171095Ssam/** 6959171095Ssam * xge_hal_rts_rth_set - Set/configure RTS hashing. 6960171095Ssam * @hldev: HAL device handle. 6961171095Ssam * @def_q: default queue 6962171095Ssam * @hash_type: hash type i.e TcpIpV4, TcpIpV6 etc. 6963171095Ssam * @bucket_size: no of least significant bits to be used for hashing. 6964171095Ssam * 6965171095Ssam * Used to set/configure all RTS hashing related stuff. 6966171095Ssam * - set the steering mode to enhanced. 6967171095Ssam * - set hash function i.e algo selection. 6968171095Ssam * - set the default queue. 6969171095Ssam * 6970171095Ssam * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(). 6971171095Ssam */ 6972171095Ssamvoid 6973171095Ssamxge_hal_rts_rth_set(xge_hal_device_t *hldev, u8 def_q, u64 hash_type, 6974173139Srwatson u16 bucket_size) 6975171095Ssam{ 6976171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6977171095Ssam u64 val64; 6978171095Ssam 6979171095Ssam val64 = XGE_HAL_RTS_DEFAULT_Q(def_q); 6980171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6981173139Srwatson &bar0->rts_default_q); 6982171095Ssam 6983171095Ssam val64 = hash_type; 6984171095Ssam val64 |= XGE_HAL_RTS_RTH_EN; 6985171095Ssam val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(bucket_size); 6986171095Ssam val64 |= XGE_HAL_RTS_RTH_ALG_SEL_MS; 6987171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6988173139Srwatson &bar0->rts_rth_cfg); 6989171095Ssam} 6990171095Ssam 6991171095Ssam/** 6992171095Ssam * xge_hal_rts_rth_start - Start RTS hashing. 6993171095Ssam * @hldev: HAL device handle. 6994171095Ssam * 6995171095Ssam * Used to Start RTS hashing . 6996171095Ssam * 6997171095Ssam * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start. 6998171095Ssam */ 6999171095Ssamvoid 7000171095Ssamxge_hal_rts_rth_start(xge_hal_device_t *hldev) 7001171095Ssam{ 7002171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7003171095Ssam u64 val64; 7004171095Ssam 7005171095Ssam 7006171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 7007173139Srwatson &bar0->rts_rth_cfg); 7008171095Ssam val64 |= XGE_HAL_RTS_RTH_EN; 7009171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7010173139Srwatson &bar0->rts_rth_cfg); 7011171095Ssam} 7012171095Ssam 7013171095Ssam/** 7014171095Ssam * xge_hal_rts_rth_stop - Stop the RTS hashing. 7015171095Ssam * @hldev: HAL device handle. 7016171095Ssam * 7017171095Ssam * Used to Staop RTS hashing . 7018171095Ssam * 7019171095Ssam * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start. 7020171095Ssam */ 7021171095Ssamvoid 7022171095Ssamxge_hal_rts_rth_stop(xge_hal_device_t *hldev) 7023171095Ssam{ 7024171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7025171095Ssam u64 val64; 7026171095Ssam 7027171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 7028173139Srwatson &bar0->rts_rth_cfg); 7029171095Ssam val64 &= ~XGE_HAL_RTS_RTH_EN; 7030171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7031173139Srwatson &bar0->rts_rth_cfg); 7032171095Ssam} 7033171095Ssam 7034171095Ssam/** 7035171095Ssam * xge_hal_rts_rth_itable_set - Set/configure indirection table (IT). 7036171095Ssam * @hldev: HAL device handle. 7037171095Ssam * @itable: Pointer to the indirection table 7038171095Ssam * @itable_size: no of least significant bits to be used for hashing 7039171095Ssam * 7040171095Ssam * Used to set/configure indirection table. 7041171095Ssam * It enables the required no of entries in the IT. 7042171095Ssam * It adds entries to the IT. 7043171095Ssam * 7044171095Ssam * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). 7045171095Ssam */ 7046171095Ssamxge_hal_status_e 7047171095Ssamxge_hal_rts_rth_itable_set(xge_hal_device_t *hldev, u8 *itable, u32 itable_size) 7048171095Ssam{ 7049173139Srwatson xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7050171095Ssam u64 val64; 7051171095Ssam u32 idx; 7052171095Ssam 7053171095Ssam for (idx = 0; idx < itable_size; idx++) { 7054173139Srwatson val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN | 7055173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_DATA(itable[idx]); 7056171095Ssam 7057173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7058173139Srwatson &bar0->rts_rth_map_mem_data); 7059171095Ssam 7060173139Srwatson /* execute */ 7061173139Srwatson val64 = (XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE | 7062173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE | 7063173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(idx)); 7064173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7065173139Srwatson &bar0->rts_rth_map_mem_ctrl); 7066171095Ssam 7067173139Srwatson /* poll until done */ 7068173139Srwatson if (__hal_device_register_poll(hldev, 7069173139Srwatson &bar0->rts_rth_map_mem_ctrl, 0, 7070173139Srwatson XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE, 7071173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 7072173139Srwatson /* upper layer may require to repeat */ 7073173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 7074173139Srwatson } 7075171095Ssam } 7076171095Ssam 7077171095Ssam return XGE_HAL_OK; 7078171095Ssam} 7079171095Ssam 7080171095Ssam 7081171095Ssam/** 7082171095Ssam * xge_hal_device_rts_rth_key_set - Configure 40byte secret for hash calc. 7083171095Ssam * 7084171095Ssam * @hldev: HAL device handle. 7085171095Ssam * @KeySize: Number of 64-bit words 7086171095Ssam * @Key: upto 40-byte array of 8-bit values 7087171095Ssam * This function configures the 40-byte secret which is used for hash 7088171095Ssam * calculation. 7089171095Ssam * 7090171095Ssam * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). 7091171095Ssam */ 7092171095Ssamvoid 7093171095Ssamxge_hal_device_rts_rth_key_set(xge_hal_device_t *hldev, u8 KeySize, u8 *Key) 7094171095Ssam{ 7095171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *) hldev->bar0; 7096171095Ssam u64 val64; 7097171095Ssam u32 entry, nreg, i; 7098171095Ssam 7099171095Ssam entry = 0; 7100171095Ssam nreg = 0; 7101171095Ssam 7102171095Ssam while( KeySize ) { 7103173139Srwatson val64 = 0; 7104173139Srwatson for ( i = 0; i < 8 ; i++) { 7105173139Srwatson /* Prepare 64-bit word for 'nreg' containing 8 keys. */ 7106173139Srwatson if (i) 7107173139Srwatson val64 <<= 8; 7108173139Srwatson val64 |= Key[entry++]; 7109173139Srwatson } 7110171095Ssam 7111173139Srwatson KeySize--; 7112171095Ssam 7113173139Srwatson /* temp64 = XGE_HAL_RTH_HASH_MASK_n(val64, (n<<3), (n<<3)+7);*/ 7114173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7115173139Srwatson &bar0->rts_rth_hash_mask[nreg++]); 7116171095Ssam } 7117171095Ssam 7118171095Ssam while( nreg < 5 ) { 7119173139Srwatson /* Clear the rest if key is less than 40 bytes */ 7120173139Srwatson val64 = 0; 7121173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7122173139Srwatson &bar0->rts_rth_hash_mask[nreg++]); 7123171095Ssam } 7124171095Ssam} 7125171095Ssam 7126171095Ssam 7127171095Ssam/** 7128171095Ssam * xge_hal_device_is_closed - Device is closed 7129171095Ssam * 7130171095Ssam * @devh: HAL device handle. 7131171095Ssam */ 7132171095Ssamint 7133171095Ssamxge_hal_device_is_closed(xge_hal_device_h devh) 7134171095Ssam{ 7135171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 7136171095Ssam 7137171095Ssam if (xge_list_is_empty(&hldev->fifo_channels) && 7138171095Ssam xge_list_is_empty(&hldev->ring_channels)) 7139173139Srwatson return 1; 7140171095Ssam 7141171095Ssam return 0; 7142171095Ssam} 7143171095Ssam 7144171095Ssamxge_hal_status_e 7145171095Ssamxge_hal_device_rts_section_enable(xge_hal_device_h devh, int index) 7146171095Ssam{ 7147171095Ssam u64 val64; 7148171095Ssam int section; 7149171095Ssam int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; 7150171095Ssam 7151171095Ssam xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 7152171095Ssam xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7153171095Ssam 7154171095Ssam if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 7155173139Srwatson max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; 7156171095Ssam 7157171095Ssam if ( index >= max_addr ) 7158173139Srwatson return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 7159171095Ssam 7160171095Ssam /* 7161171095Ssam * Calculate the section value 7162171095Ssam */ 7163171095Ssam section = index / 32; 7164171095Ssam 7165173139Srwatson xge_debug_device(XGE_TRACE, "the Section value is %d ", section); 7166171095Ssam 7167171095Ssam val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 7168173139Srwatson &bar0->rts_mac_cfg); 7169171095Ssam switch(section) 7170171095Ssam { 7171173139Srwatson case 0: 7172173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT0_EN; 7173173139Srwatson break; 7174173139Srwatson case 1: 7175173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT1_EN; 7176173139Srwatson break; 7177173139Srwatson case 2: 7178173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT2_EN; 7179173139Srwatson break; 7180173139Srwatson case 3: 7181173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT3_EN; 7182173139Srwatson break; 7183173139Srwatson case 4: 7184173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT4_EN; 7185173139Srwatson break; 7186173139Srwatson case 5: 7187173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT5_EN; 7188173139Srwatson break; 7189173139Srwatson case 6: 7190173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT6_EN; 7191173139Srwatson break; 7192173139Srwatson case 7: 7193173139Srwatson val64 |= XGE_HAL_RTS_MAC_SECT7_EN; 7194173139Srwatson break; 7195173139Srwatson default: 7196173139Srwatson xge_debug_device(XGE_ERR, "Invalid Section value %d " 7197173139Srwatson , section); 7198173139Srwatson } 7199171095Ssam 7200171095Ssam xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 7201173139Srwatson val64, &bar0->rts_mac_cfg); 7202171095Ssam return XGE_HAL_OK; 7203171095Ssam} 7204171095Ssam 7205171095Ssam 7206173139Srwatson/** 7207173139Srwatson * xge_hal_fix_rldram_ecc_error 7208173139Srwatson * @hldev: private member of the device structure. 7209173139Srwatson * 7210173139Srwatson * SXE-02-010. This function will turn OFF the ECC error reporting for the 7211173139Srwatson * interface bet'n external Micron RLDRAM II device and memory controller. 7212173139Srwatson * The error would have been reported in RLD_ECC_DB_ERR_L and RLD_ECC_DB_ERR_U 7213173139Srwatson * fields of MC_ERR_REG register. Issue reported by HP-Unix folks during the 7214173139Srwatson * qualification of Herc. 7215173139Srwatson */ 7216173139Srwatsonxge_hal_status_e 7217173139Srwatsonxge_hal_fix_rldram_ecc_error(xge_hal_device_t * hldev) 7218173139Srwatson{ 7219173139Srwatson xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 7220173139Srwatson u64 val64; 7221173139Srwatson 7222173139Srwatson // Enter Test Mode. 7223173139Srwatson val64 = XGE_HAL_MC_RLDRAM_TEST_MODE; 7224173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7225173139Srwatson &bar0->mc_rldram_test_ctrl); 7226173139Srwatson 7227173139Srwatson // Enable fg/bg tests. 7228173139Srwatson val64 = 0x0100000000000000ULL; 7229173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7230173139Srwatson &bar0->mc_driver); 7231173139Srwatson 7232173139Srwatson // Enable RLDRAM configuration. 7233173139Srwatson val64 = 0x0000000000017B00ULL; 7234173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7235173139Srwatson &bar0->mc_rldram_mrs); 7236173139Srwatson 7237173139Srwatson // Enable RLDRAM queues. 7238173139Srwatson val64 = 0x0000000001017B00ULL; 7239173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7240173139Srwatson &bar0->mc_rldram_mrs); 7241173139Srwatson 7242173139Srwatson // Setup test ranges 7243173139Srwatson val64 = 0x00000000001E0100ULL; 7244173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7245173139Srwatson &bar0->mc_rldram_test_add); 7246173139Srwatson 7247173139Srwatson val64 = 0x00000100001F0100ULL; 7248173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7249173139Srwatson &bar0->mc_rldram_test_add_bkg); 7250173139Srwatson // Start Reads. 7251173139Srwatson val64 = 0x0001000000010000ULL; 7252173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7253173139Srwatson &bar0->mc_rldram_test_ctrl); 7254173139Srwatson 7255173139Srwatson if (__hal_device_register_poll(hldev, &bar0->mc_rldram_test_ctrl, 1, 7256173139Srwatson XGE_HAL_MC_RLDRAM_TEST_DONE, 7257173139Srwatson XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK){ 7258173139Srwatson return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 7259173139Srwatson } 7260173139Srwatson 7261173139Srwatson // Exit test mode 7262173139Srwatson val64 = 0x0000000000000000ULL; 7263173139Srwatson xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7264173139Srwatson &bar0->mc_rldram_test_ctrl); 7265173139Srwatson 7266173139Srwatson return XGE_HAL_OK; 7267173139Srwatson} 7268