1a23fd118Syl /* 2a23fd118Syl * CDDL HEADER START 3a23fd118Syl * 4a23fd118Syl * The contents of this file are subject to the terms of the 5a23fd118Syl * Common Development and Distribution License (the "License"). 6a23fd118Syl * You may not use this file except in compliance with the License. 7a23fd118Syl * 8a23fd118Syl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9a23fd118Syl * or http://www.opensolaris.org/os/licensing. 10a23fd118Syl * See the License for the specific language governing permissions 11a23fd118Syl * and limitations under the License. 12a23fd118Syl * 13a23fd118Syl * When distributing Covered Code, include this CDDL HEADER in each 14a23fd118Syl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15a23fd118Syl * If applicable, add the following below this CDDL HEADER, with the 16a23fd118Syl * fields enclosed by brackets "[]" replaced with your own identifying 17a23fd118Syl * information: Portions Copyright [yyyy] [name of copyright owner] 18a23fd118Syl * 19a23fd118Syl * CDDL HEADER END 20a23fd118Syl * 218347601bSyl * Copyright (c) 2002-2006 Neterion, Inc. 22a23fd118Syl */ 23a23fd118Syl 24*19397407SSherry Moore /* 25*19397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26*19397407SSherry Moore * Use is subject to license terms. 27*19397407SSherry Moore */ 28*19397407SSherry Moore 29a23fd118Syl #include "xgehal-device.h" 30a23fd118Syl #include "xgehal-channel.h" 31a23fd118Syl #include "xgehal-fifo.h" 32a23fd118Syl #include "xgehal-ring.h" 33a23fd118Syl #include "xgehal-driver.h" 34a23fd118Syl #include "xgehal-mgmt.h" 35a23fd118Syl 36a23fd118Syl #define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL 37a23fd118Syl #define END_SIGN 0x0 38a23fd118Syl 39a23fd118Syl #ifdef XGE_HAL_HERC_EMULATION 40a23fd118Syl #undef XGE_HAL_PROCESS_LINK_INT_IN_ISR 41a23fd118Syl #endif 42a23fd118Syl 43a23fd118Syl /* 44a23fd118Syl * Jenkins hash key length(in bytes) 45a23fd118Syl */ 46a23fd118Syl #define XGE_HAL_JHASH_MSG_LEN 50 47a23fd118Syl 48a23fd118Syl /* 49a23fd118Syl * mix(a,b,c) used in Jenkins hash algorithm 50a23fd118Syl */ 51a23fd118Syl #define mix(a,b,c) { \ 52a23fd118Syl a -= b; a -= c; a ^= (c>>13); \ 53a23fd118Syl b -= c; b -= a; b ^= (a<<8); \ 54a23fd118Syl c -= a; c -= b; c ^= (b>>13); \ 55a23fd118Syl a -= b; a -= c; a ^= (c>>12); \ 56a23fd118Syl b -= c; b -= a; b ^= (a<<16); \ 57a23fd118Syl c -= a; c -= b; c ^= (b>>5); \ 58a23fd118Syl a -= b; a -= c; a ^= (c>>3); \ 59a23fd118Syl b -= c; b -= a; b ^= (a<<10); \ 60a23fd118Syl c -= a; c -= b; c ^= (b>>15); \ 61a23fd118Syl } 62a23fd118Syl 63a23fd118Syl 64a23fd118Syl /* 65a23fd118Syl * __hal_device_event_queued 66a23fd118Syl * @data: pointer to xge_hal_device_t structure 67a23fd118Syl * 68a23fd118Syl * Will be called when new event succesfully queued. 69a23fd118Syl */ 70a23fd118Syl void 71a23fd118Syl __hal_device_event_queued(void *data, int event_type) 72a23fd118Syl { 73a23fd118Syl xge_assert(((xge_hal_device_t*)data)->magic == XGE_HAL_MAGIC); 74a23fd118Syl if (g_xge_hal_driver->uld_callbacks.event_queued) { 75a23fd118Syl g_xge_hal_driver->uld_callbacks.event_queued(data, event_type); 76a23fd118Syl } 77a23fd118Syl } 78a23fd118Syl 79a23fd118Syl /* 80a23fd118Syl * __hal_pio_mem_write32_upper 81a23fd118Syl * 82a23fd118Syl * Endiann-aware implementation of xge_os_pio_mem_write32(). 83a23fd118Syl * Since Xframe has 64bit registers, we differintiate uppper and lower 84a23fd118Syl * parts. 85a23fd118Syl */ 86a23fd118Syl void 87a23fd118Syl __hal_pio_mem_write32_upper(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr) 88a23fd118Syl { 89a23fd118Syl #if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) 90a23fd118Syl xge_os_pio_mem_write32(pdev, regh, val, addr); 91a23fd118Syl #else 92a23fd118Syl xge_os_pio_mem_write32(pdev, regh, val, (void *)((char *)addr + 4)); 93a23fd118Syl #endif 94a23fd118Syl } 95a23fd118Syl 96a23fd118Syl /* 97a23fd118Syl * __hal_pio_mem_write32_upper 98a23fd118Syl * 99a23fd118Syl * Endiann-aware implementation of xge_os_pio_mem_write32(). 100a23fd118Syl * Since Xframe has 64bit registers, we differintiate uppper and lower 101a23fd118Syl * parts. 102a23fd118Syl */ 103a23fd118Syl void 104a23fd118Syl __hal_pio_mem_write32_lower(pci_dev_h pdev, pci_reg_h regh, u32 val, 105a23fd118Syl void *addr) 106a23fd118Syl { 107a23fd118Syl #if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN) 108a23fd118Syl xge_os_pio_mem_write32(pdev, regh, val, 109a23fd118Syl (void *) ((char *)addr + 4)); 110a23fd118Syl #else 111a23fd118Syl xge_os_pio_mem_write32(pdev, regh, val, addr); 112a23fd118Syl #endif 113a23fd118Syl } 114a23fd118Syl 115a23fd118Syl /* 116a23fd118Syl * __hal_device_register_poll 117a23fd118Syl * @hldev: pointer to xge_hal_device_t structure 118a23fd118Syl * @reg: register to poll for 119a23fd118Syl * @op: 0 - bit reset, 1 - bit set 120a23fd118Syl * @mask: mask for logical "and" condition based on %op 121a23fd118Syl * @max_millis: maximum time to try to poll in milliseconds 122a23fd118Syl * 123a23fd118Syl * Will poll certain register for specified amount of time. 124a23fd118Syl * Will poll until masked bit is not cleared. 125a23fd118Syl */ 126a23fd118Syl xge_hal_status_e 127a23fd118Syl __hal_device_register_poll(xge_hal_device_t *hldev, u64 *reg, 128a23fd118Syl int op, u64 mask, int max_millis) 129a23fd118Syl { 130a23fd118Syl u64 val64; 131a23fd118Syl int i = 0; 1328347601bSyl xge_hal_status_e ret = XGE_HAL_FAIL; 1338347601bSyl 1348347601bSyl xge_os_udelay(10); 135a23fd118Syl 136a23fd118Syl do { 137a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg); 1388347601bSyl if (op == 0 && !(val64 & mask)) 1398347601bSyl return XGE_HAL_OK; 1408347601bSyl else if (op == 1 && (val64 & mask) == mask) 1418347601bSyl return XGE_HAL_OK; 1428347601bSyl xge_os_udelay(100); 1438347601bSyl } while (++i <= 9); 1448347601bSyl 1458347601bSyl do { 1468347601bSyl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg); 1478347601bSyl if (op == 0 && !(val64 & mask)) 1488347601bSyl return XGE_HAL_OK; 1498347601bSyl else if (op == 1 && (val64 & mask) == mask) 1508347601bSyl return XGE_HAL_OK; 1518347601bSyl xge_os_udelay(1000); 1528347601bSyl } while (++i < max_millis); 153a23fd118Syl 154a23fd118Syl return ret; 155a23fd118Syl } 156a23fd118Syl 157a23fd118Syl /* 158a23fd118Syl * __hal_device_wait_quiescent 159a23fd118Syl * @hldev: the device 160a23fd118Syl * @hw_status: hw_status in case of error 161a23fd118Syl * 162a23fd118Syl * Will wait until device is quiescent for some blocks. 163a23fd118Syl */ 164a23fd118Syl static xge_hal_status_e 165a23fd118Syl __hal_device_wait_quiescent(xge_hal_device_t *hldev, u64 *hw_status) 166a23fd118Syl { 167a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 168a23fd118Syl 169a23fd118Syl /* poll and wait first */ 170a23fd118Syl #ifdef XGE_HAL_HERC_EMULATION 171a23fd118Syl (void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1, 172a23fd118Syl (XGE_HAL_ADAPTER_STATUS_TDMA_READY | 173a23fd118Syl XGE_HAL_ADAPTER_STATUS_RDMA_READY | 174a23fd118Syl XGE_HAL_ADAPTER_STATUS_PFC_READY | 175a23fd118Syl XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY | 176a23fd118Syl XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT | 177a23fd118Syl XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY | 178a23fd118Syl XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY | 179a23fd118Syl XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK), 180a23fd118Syl XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS); 181a23fd118Syl #else 182a23fd118Syl (void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1, 183a23fd118Syl (XGE_HAL_ADAPTER_STATUS_TDMA_READY | 184a23fd118Syl XGE_HAL_ADAPTER_STATUS_RDMA_READY | 185a23fd118Syl XGE_HAL_ADAPTER_STATUS_PFC_READY | 186a23fd118Syl XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY | 187a23fd118Syl XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT | 188a23fd118Syl XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY | 189a23fd118Syl XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY | 190a23fd118Syl XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK | 191a23fd118Syl XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK), 192a23fd118Syl XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS); 193a23fd118Syl #endif 194a23fd118Syl 195a23fd118Syl return xge_hal_device_status(hldev, hw_status); 196a23fd118Syl } 197a23fd118Syl 198a23fd118Syl /** 199a23fd118Syl * xge_hal_device_is_slot_freeze 2008347601bSyl * @devh: the device 201a23fd118Syl * 202a23fd118Syl * Returns non-zero if the slot is freezed. 203a23fd118Syl * The determination is made based on the adapter_status 204a23fd118Syl * register which will never give all FFs, unless PCI read 205a23fd118Syl * cannot go through. 206a23fd118Syl */ 207a23fd118Syl int 208a23fd118Syl xge_hal_device_is_slot_freeze(xge_hal_device_h devh) 209a23fd118Syl { 210a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 211a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 212a23fd118Syl u16 device_id; 213a23fd118Syl u64 adapter_status = 214a23fd118Syl xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 215a23fd118Syl &bar0->adapter_status); 216a23fd118Syl xge_os_pci_read16(hldev->pdev,hldev->cfgh, 217a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, device_id), 218a23fd118Syl &device_id); 219a23fd118Syl #ifdef TX_DEBUG 2208347601bSyl if (adapter_status == XGE_HAL_ALL_FOXES) 221a23fd118Syl { 2228347601bSyl u64 dummy; 2238347601bSyl dummy = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2248347601bSyl &bar0->pcc_enable); 2258347601bSyl printf(">>> Slot is frozen!\n"); 2268347601bSyl brkpoint(0); 227a23fd118Syl } 228a23fd118Syl #endif 2298347601bSyl return((adapter_status == XGE_HAL_ALL_FOXES) || (device_id == 0xffff)); 230a23fd118Syl } 231a23fd118Syl 232a23fd118Syl 233a23fd118Syl /* 234a23fd118Syl * __hal_device_led_actifity_fix 235a23fd118Syl * @hldev: pointer to xge_hal_device_t structure 236a23fd118Syl * 237a23fd118Syl * SXE-002: Configure link and activity LED to turn it off 238a23fd118Syl */ 239a23fd118Syl static void 240a23fd118Syl __hal_device_led_actifity_fix(xge_hal_device_t *hldev) 241a23fd118Syl { 242a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 243a23fd118Syl u16 subid; 244a23fd118Syl u64 val64; 245a23fd118Syl 246a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 247a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), &subid); 248a23fd118Syl 249a23fd118Syl /* 250a23fd118Syl * In the case of Herc, there is a new register named beacon control 251a23fd118Syl * is added which was not present in Xena. 252a23fd118Syl * Beacon control register in Herc is at the same offset as 253a23fd118Syl * gpio control register in Xena. It means they are one and same in 254a23fd118Syl * the case of Xena. Also, gpio control register offset in Herc and 255a23fd118Syl * Xena is different. 256a23fd118Syl * The current register map represents Herc(It means we have 257a23fd118Syl * both beacon and gpio control registers in register map). 258a23fd118Syl * WRT transition from Xena to Herc, all the code in Xena which was 259a23fd118Syl * using gpio control register for LED handling would have to 260a23fd118Syl * use beacon control register in Herc and the rest of the code 261a23fd118Syl * which uses gpio control in Xena would use the same register 262a23fd118Syl * in Herc. 263a23fd118Syl * WRT LED handling(following code), In the case of Herc, beacon 264a23fd118Syl * control register has to be used. This is applicable for Xena also, 265a23fd118Syl * since it represents the gpio control register in Xena. 266a23fd118Syl */ 267a23fd118Syl if ((subid & 0xFF) >= 0x07) { 268a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 269a23fd118Syl &bar0->beacon_control); 270a23fd118Syl val64 |= 0x0000800000000000ULL; 271a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 272a23fd118Syl val64, &bar0->beacon_control); 273a23fd118Syl val64 = 0x0411040400000000ULL; 274a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 275a23fd118Syl (void *) ((u8 *)bar0 + 0x2700)); 276a23fd118Syl } 277a23fd118Syl } 278a23fd118Syl 279a23fd118Syl /* Constants for Fixing the MacAddress problem seen mostly on 280a23fd118Syl * Alpha machines. 281a23fd118Syl */ 282a23fd118Syl static u64 xena_fix_mac[] = { 283a23fd118Syl 0x0060000000000000ULL, 0x0060600000000000ULL, 284a23fd118Syl 0x0040600000000000ULL, 0x0000600000000000ULL, 285a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 286a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 287a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 288a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 289a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 290a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 291a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 292a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 293a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 294a23fd118Syl 0x0020600000000000ULL, 0x0060600000000000ULL, 295a23fd118Syl 0x0020600000000000ULL, 0x0000600000000000ULL, 296a23fd118Syl 0x0040600000000000ULL, 0x0060600000000000ULL, 297a23fd118Syl END_SIGN 298a23fd118Syl }; 299a23fd118Syl 300a23fd118Syl /* 301a23fd118Syl * __hal_device_fix_mac 302a23fd118Syl * @hldev: HAL device handle. 303a23fd118Syl * 304a23fd118Syl * Fix for all "FFs" MAC address problems observed on Alpha platforms. 305a23fd118Syl */ 306a23fd118Syl static void 307a23fd118Syl __hal_device_xena_fix_mac(xge_hal_device_t *hldev) 308a23fd118Syl { 309a23fd118Syl int i = 0; 310a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 311a23fd118Syl 312a23fd118Syl /* 313a23fd118Syl * In the case of Herc, there is a new register named beacon control 314a23fd118Syl * is added which was not present in Xena. 315a23fd118Syl * Beacon control register in Herc is at the same offset as 316a23fd118Syl * gpio control register in Xena. It means they are one and same in 317a23fd118Syl * the case of Xena. Also, gpio control register offset in Herc and 318a23fd118Syl * Xena is different. 319a23fd118Syl * The current register map represents Herc(It means we have 320a23fd118Syl * both beacon and gpio control registers in register map). 321a23fd118Syl * WRT transition from Xena to Herc, all the code in Xena which was 322a23fd118Syl * using gpio control register for LED handling would have to 323a23fd118Syl * use beacon control register in Herc and the rest of the code 324a23fd118Syl * which uses gpio control in Xena would use the same register 325a23fd118Syl * in Herc. 326a23fd118Syl * In the following code(xena_fix_mac), beacon control register has 327a23fd118Syl * to be used in the case of Xena, since it represents gpio control 328a23fd118Syl * register. In the case of Herc, there is no change required. 329a23fd118Syl */ 330a23fd118Syl while (xena_fix_mac[i] != END_SIGN) { 331a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 332a23fd118Syl xena_fix_mac[i++], &bar0->beacon_control); 333a23fd118Syl xge_os_mdelay(1); 334a23fd118Syl } 335a23fd118Syl } 336a23fd118Syl 337a23fd118Syl /* 338a23fd118Syl * xge_hal_device_bcast_enable 339a23fd118Syl * @hldev: HAL device handle. 340a23fd118Syl * 341a23fd118Syl * Enable receiving broadcasts. 342a23fd118Syl * The host must first write RMAC_CFG_KEY "key" 343a23fd118Syl * register, and then - MAC_CFG register. 344a23fd118Syl */ 345a23fd118Syl void 346a23fd118Syl xge_hal_device_bcast_enable(xge_hal_device_h devh) 347a23fd118Syl { 348a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 349a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 350a23fd118Syl u64 val64; 351a23fd118Syl 352a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 353a23fd118Syl &bar0->mac_cfg); 354a23fd118Syl val64 |= XGE_HAL_MAC_RMAC_BCAST_ENABLE; 355a23fd118Syl 356a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 357a23fd118Syl XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); 358a23fd118Syl 359a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 360a23fd118Syl (u32)(val64 >> 32), &bar0->mac_cfg); 361a23fd118Syl 3628347601bSyl xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s", 363a23fd118Syl (unsigned long long)val64, 364a23fd118Syl hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled"); 365a23fd118Syl } 366a23fd118Syl 367a23fd118Syl /* 368a23fd118Syl * xge_hal_device_bcast_disable 369a23fd118Syl * @hldev: HAL device handle. 370a23fd118Syl * 371a23fd118Syl * Disable receiving broadcasts. 372a23fd118Syl * The host must first write RMAC_CFG_KEY "key" 373a23fd118Syl * register, and then - MAC_CFG register. 374a23fd118Syl */ 375a23fd118Syl void 376a23fd118Syl xge_hal_device_bcast_disable(xge_hal_device_h devh) 377a23fd118Syl { 378a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 379a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 380a23fd118Syl u64 val64; 381a23fd118Syl 382a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 383a23fd118Syl &bar0->mac_cfg); 384a23fd118Syl 385a23fd118Syl val64 &= ~(XGE_HAL_MAC_RMAC_BCAST_ENABLE); 386a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 387a23fd118Syl XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); 388a23fd118Syl 389a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 390a23fd118Syl (u32)(val64 >> 32), &bar0->mac_cfg); 391a23fd118Syl 3928347601bSyl xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s", 393a23fd118Syl (unsigned long long)val64, 394a23fd118Syl hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled"); 395a23fd118Syl } 396a23fd118Syl 397a23fd118Syl /* 398a23fd118Syl * __hal_device_shared_splits_configure 399a23fd118Syl * @hldev: HAL device handle. 400a23fd118Syl * 401a23fd118Syl * TxDMA will stop Read request if the number of read split had exceeded 402a23fd118Syl * the limit set by shared_splits 403a23fd118Syl */ 404a23fd118Syl static void 405a23fd118Syl __hal_device_shared_splits_configure(xge_hal_device_t *hldev) 406a23fd118Syl { 407a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 408a23fd118Syl u64 val64; 409a23fd118Syl 410a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 411a23fd118Syl &bar0->pic_control); 412a23fd118Syl val64 |= 413a23fd118Syl XGE_HAL_PIC_CNTL_SHARED_SPLITS(hldev->config.shared_splits); 414a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 415a23fd118Syl &bar0->pic_control); 416a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "shared splits configured"); 417a23fd118Syl } 418a23fd118Syl 419a23fd118Syl /* 420a23fd118Syl * __hal_device_rmac_padding_configure 421a23fd118Syl * @hldev: HAL device handle. 422a23fd118Syl * 423a23fd118Syl * Configure RMAC frame padding. Depends on configuration, it 424a23fd118Syl * can be send to host or removed by MAC. 425a23fd118Syl */ 426a23fd118Syl static void 427a23fd118Syl __hal_device_rmac_padding_configure(xge_hal_device_t *hldev) 428a23fd118Syl { 429a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 430a23fd118Syl u64 val64; 431a23fd118Syl 432a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 433a23fd118Syl XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); 434a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 435a23fd118Syl &bar0->mac_cfg); 436a23fd118Syl val64 &= ( ~XGE_HAL_MAC_RMAC_ALL_ADDR_ENABLE ); 437a23fd118Syl val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE ); 438a23fd118Syl val64 |= XGE_HAL_MAC_CFG_TMAC_APPEND_PAD; 439a23fd118Syl 440a23fd118Syl /* 441a23fd118Syl * If the RTH enable bit is not set, strip the FCS 442a23fd118Syl */ 443a23fd118Syl if (!hldev->config.rth_en || 444a23fd118Syl !(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 445a23fd118Syl &bar0->rts_rth_cfg) & XGE_HAL_RTS_RTH_EN)) { 446a23fd118Syl val64 |= XGE_HAL_MAC_CFG_RMAC_STRIP_FCS; 447a23fd118Syl } 448a23fd118Syl 449a23fd118Syl val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_STRIP_PAD ); 450a23fd118Syl val64 |= XGE_HAL_MAC_RMAC_DISCARD_PFRM; 451a23fd118Syl 452a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 453a23fd118Syl (u32)(val64 >> 32), (char*)&bar0->mac_cfg); 454a23fd118Syl xge_os_mdelay(1); 455a23fd118Syl 456a23fd118Syl xge_debug_device(XGE_TRACE, 4578347601bSyl "mac_cfg 0x"XGE_OS_LLXFMT": frame padding configured", 4588347601bSyl (unsigned long long)val64); 459a23fd118Syl } 460a23fd118Syl 461a23fd118Syl /* 462a23fd118Syl * __hal_device_pause_frames_configure 463a23fd118Syl * @hldev: HAL device handle. 464a23fd118Syl * 465a23fd118Syl * Set Pause threshold. 466a23fd118Syl * 467a23fd118Syl * Pause frame is generated if the amount of data outstanding 468a23fd118Syl * on any queue exceeded the ratio of 469a23fd118Syl * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256 470a23fd118Syl */ 471a23fd118Syl static void 472a23fd118Syl __hal_device_pause_frames_configure(xge_hal_device_t *hldev) 473a23fd118Syl { 474a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 475a23fd118Syl int i; 476a23fd118Syl u64 val64; 477a23fd118Syl 478a23fd118Syl switch (hldev->config.mac.media) { 479a23fd118Syl case XGE_HAL_MEDIA_SR: 480a23fd118Syl case XGE_HAL_MEDIA_SW: 481a23fd118Syl val64=0xfffbfffbfffbfffbULL; 482a23fd118Syl break; 483a23fd118Syl case XGE_HAL_MEDIA_LR: 484a23fd118Syl case XGE_HAL_MEDIA_LW: 485a23fd118Syl val64=0xffbbffbbffbbffbbULL; 486a23fd118Syl break; 487a23fd118Syl case XGE_HAL_MEDIA_ER: 488a23fd118Syl case XGE_HAL_MEDIA_EW: 489a23fd118Syl default: 490a23fd118Syl val64=0xffbbffbbffbbffbbULL; 491a23fd118Syl break; 492a23fd118Syl } 493a23fd118Syl 494a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 495a23fd118Syl val64, &bar0->mc_pause_thresh_q0q3); 496a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 497a23fd118Syl val64, &bar0->mc_pause_thresh_q4q7); 498a23fd118Syl 499a23fd118Syl /* Set the time value to be inserted in the pause frame generated 500a23fd118Syl * by Xframe */ 501a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 502a23fd118Syl &bar0->rmac_pause_cfg); 503a23fd118Syl if (hldev->config.mac.rmac_pause_gen_en) 504a23fd118Syl val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN; 505a23fd118Syl else 506a23fd118Syl val64 &= ~(XGE_HAL_RMAC_PAUSE_GEN_EN); 507a23fd118Syl if (hldev->config.mac.rmac_pause_rcv_en) 508a23fd118Syl val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN; 509a23fd118Syl else 510a23fd118Syl val64 &= ~(XGE_HAL_RMAC_PAUSE_RCV_EN); 511a23fd118Syl val64 &= ~(XGE_HAL_RMAC_PAUSE_HG_PTIME(0xffff)); 512a23fd118Syl val64 |= XGE_HAL_RMAC_PAUSE_HG_PTIME(hldev->config.mac.rmac_pause_time); 513a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 514a23fd118Syl &bar0->rmac_pause_cfg); 515a23fd118Syl 516a23fd118Syl val64 = 0; 517a23fd118Syl for (i = 0; i<4; i++) { 518a23fd118Syl val64 |= 519a23fd118Syl (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q0q3) 520a23fd118Syl <<(i*2*8)); 521a23fd118Syl } 522a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 523a23fd118Syl &bar0->mc_pause_thresh_q0q3); 524a23fd118Syl 525a23fd118Syl val64 = 0; 526a23fd118Syl for (i = 0; i<4; i++) { 527a23fd118Syl val64 |= 528a23fd118Syl (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q4q7) 529a23fd118Syl <<(i*2*8)); 530a23fd118Syl } 531a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 532a23fd118Syl &bar0->mc_pause_thresh_q4q7); 533a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "pause frames configured"); 534a23fd118Syl } 535a23fd118Syl 536a23fd118Syl /* 537a23fd118Syl * Herc's clock rate doubled, unless the slot is 33MHz. 538a23fd118Syl */ 539a23fd118Syl unsigned int __hal_fix_time_ival_herc(xge_hal_device_t *hldev, 540a23fd118Syl unsigned int time_ival) 541a23fd118Syl { 542a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 543a23fd118Syl return time_ival; 544a23fd118Syl 545a23fd118Syl xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC); 546a23fd118Syl 547a23fd118Syl if (hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN && 548a23fd118Syl hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_33MHZ) 549a23fd118Syl time_ival *= 2; 550a23fd118Syl 551a23fd118Syl return time_ival; 552a23fd118Syl } 553a23fd118Syl 554a23fd118Syl 555a23fd118Syl /* 556a23fd118Syl * __hal_device_bus_master_disable 557a23fd118Syl * @hldev: HAL device handle. 558a23fd118Syl * 559a23fd118Syl * Disable bus mastership. 560a23fd118Syl */ 561a23fd118Syl static void 562a23fd118Syl __hal_device_bus_master_disable (xge_hal_device_t *hldev) 563a23fd118Syl { 564a23fd118Syl u16 cmd; 565a23fd118Syl u16 bus_master = 4; 566a23fd118Syl 567a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 568a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); 569a23fd118Syl cmd &= ~bus_master; 570a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 571a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, command), cmd); 572a23fd118Syl } 573a23fd118Syl 574a23fd118Syl /* 575a23fd118Syl * __hal_device_bus_master_enable 576a23fd118Syl * @hldev: HAL device handle. 577a23fd118Syl * 578a23fd118Syl * Disable bus mastership. 579a23fd118Syl */ 580a23fd118Syl static void 581a23fd118Syl __hal_device_bus_master_enable (xge_hal_device_t *hldev) 582a23fd118Syl { 583a23fd118Syl u16 cmd; 584a23fd118Syl u16 bus_master = 4; 585a23fd118Syl 586a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 587a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); 588a23fd118Syl 589a23fd118Syl /* already enabled? do nothing */ 590a23fd118Syl if (cmd & bus_master) 591a23fd118Syl return; 592a23fd118Syl 593a23fd118Syl cmd |= bus_master; 594a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 595a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, command), cmd); 596a23fd118Syl } 597a23fd118Syl /* 598a23fd118Syl * __hal_device_intr_mgmt 599a23fd118Syl * @hldev: HAL device handle. 600a23fd118Syl * @mask: mask indicating which Intr block must be modified. 601a23fd118Syl * @flag: if true - enable, otherwise - disable interrupts. 602a23fd118Syl * 603a23fd118Syl * Disable or enable device interrupts. Mask is used to specify 604a23fd118Syl * which hardware blocks should produce interrupts. For details 605a23fd118Syl * please refer to Xframe User Guide. 606a23fd118Syl */ 607a23fd118Syl static void 608a23fd118Syl __hal_device_intr_mgmt(xge_hal_device_t *hldev, u64 mask, int flag) 609a23fd118Syl { 610a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 611a23fd118Syl u64 val64 = 0, temp64 = 0; 612a23fd118Syl u64 gim, gim_saved; 613a23fd118Syl 614a23fd118Syl gim_saved = gim = xge_os_pio_mem_read64(hldev->pdev, 615a23fd118Syl hldev->regh0, &bar0->general_int_mask); 616a23fd118Syl 617a23fd118Syl /* Top level interrupt classification */ 618a23fd118Syl /* PIC Interrupts */ 619a23fd118Syl if ((mask & (XGE_HAL_TX_PIC_INTR/* | XGE_HAL_RX_PIC_INTR*/))) { 620a23fd118Syl /* Enable PIC Intrs in the general intr mask register */ 621a23fd118Syl val64 = XGE_HAL_TXPIC_INT_M/* | XGE_HAL_PIC_RX_INT_M*/; 622a23fd118Syl if (flag) { 623a23fd118Syl gim &= ~((u64) val64); 624a23fd118Syl temp64 = xge_os_pio_mem_read64(hldev->pdev, 625a23fd118Syl hldev->regh0, &bar0->pic_int_mask); 626a23fd118Syl 627a23fd118Syl temp64 &= ~XGE_HAL_PIC_INT_TX; 628a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 629a23fd118Syl if (xge_hal_device_check_id(hldev) == 630a23fd118Syl XGE_HAL_CARD_HERC) { 631a23fd118Syl temp64 &= ~XGE_HAL_PIC_INT_MISC; 632a23fd118Syl } 633a23fd118Syl #endif 634a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 635a23fd118Syl temp64, &bar0->pic_int_mask); 636a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 637a23fd118Syl if (xge_hal_device_check_id(hldev) == 638a23fd118Syl XGE_HAL_CARD_HERC) { 639a23fd118Syl /* 640a23fd118Syl * Unmask only Link Up interrupt 641a23fd118Syl */ 642a23fd118Syl temp64 = xge_os_pio_mem_read64(hldev->pdev, 643a23fd118Syl hldev->regh0, &bar0->misc_int_mask); 644a23fd118Syl temp64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; 645a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 646a23fd118Syl hldev->regh0, temp64, 647a23fd118Syl &bar0->misc_int_mask); 648a23fd118Syl xge_debug_device(XGE_TRACE, 6498347601bSyl "unmask link up flag "XGE_OS_LLXFMT, 650a23fd118Syl (unsigned long long)temp64); 651a23fd118Syl } 652a23fd118Syl #endif 653a23fd118Syl } else { /* flag == 0 */ 654a23fd118Syl 655a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 656a23fd118Syl if (xge_hal_device_check_id(hldev) == 657a23fd118Syl XGE_HAL_CARD_HERC) { 658a23fd118Syl /* 659a23fd118Syl * Mask both Link Up and Down interrupts 660a23fd118Syl */ 661a23fd118Syl temp64 = xge_os_pio_mem_read64(hldev->pdev, 662a23fd118Syl hldev->regh0, &bar0->misc_int_mask); 663a23fd118Syl temp64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; 664a23fd118Syl temp64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 665a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 666a23fd118Syl hldev->regh0, temp64, 667a23fd118Syl &bar0->misc_int_mask); 668a23fd118Syl xge_debug_device(XGE_TRACE, 6698347601bSyl "mask link up/down flag "XGE_OS_LLXFMT, 670a23fd118Syl (unsigned long long)temp64); 671a23fd118Syl } 672a23fd118Syl #endif 673a23fd118Syl /* Disable PIC Intrs in the general intr mask 674a23fd118Syl * register */ 675a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 676a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 677a23fd118Syl &bar0->pic_int_mask); 678a23fd118Syl gim |= val64; 679a23fd118Syl } 680a23fd118Syl } 681a23fd118Syl 682a23fd118Syl /* DMA Interrupts */ 683a23fd118Syl /* Enabling/Disabling Tx DMA interrupts */ 684a23fd118Syl if (mask & XGE_HAL_TX_DMA_INTR) { 685a23fd118Syl /* Enable TxDMA Intrs in the general intr mask register */ 686a23fd118Syl val64 = XGE_HAL_TXDMA_INT_M; 687a23fd118Syl if (flag) { 688a23fd118Syl gim &= ~((u64) val64); 6897eced415Sxw /* Enable all TxDMA interrupts */ 690a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6917eced415Sxw 0x0, &bar0->txdma_int_mask); 692a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6937eced415Sxw 0x0, &bar0->pfc_err_mask); 6947eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6957eced415Sxw 0x0, &bar0->tda_err_mask); 6967eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6977eced415Sxw 0x0, &bar0->pcc_err_mask); 6987eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6997eced415Sxw 0x0, &bar0->tti_err_mask); 7007eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 7017eced415Sxw 0x0, &bar0->lso_err_mask); 7027eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 7037eced415Sxw 0x0, &bar0->tpa_err_mask); 7047eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 7057eced415Sxw 0x0, &bar0->sm_err_mask); 706a23fd118Syl 707a23fd118Syl } else { /* flag == 0 */ 708a23fd118Syl 709a23fd118Syl /* Disable TxDMA Intrs in the general intr mask 710a23fd118Syl * register */ 711a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 712a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 713a23fd118Syl &bar0->txdma_int_mask); 714a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 715a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 716a23fd118Syl &bar0->pfc_err_mask); 717a23fd118Syl 718a23fd118Syl gim |= val64; 719a23fd118Syl } 720a23fd118Syl } 721a23fd118Syl 722a23fd118Syl /* Enabling/Disabling Rx DMA interrupts */ 723a23fd118Syl if (mask & XGE_HAL_RX_DMA_INTR) { 724a23fd118Syl /* Enable RxDMA Intrs in the general intr mask register */ 725a23fd118Syl val64 = XGE_HAL_RXDMA_INT_M; 726a23fd118Syl if (flag) { 727a23fd118Syl 728a23fd118Syl gim &= ~((u64) val64); 729a23fd118Syl /* All RxDMA block interrupts are disabled for now 730a23fd118Syl * TODO */ 731a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 732a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 733a23fd118Syl &bar0->rxdma_int_mask); 734a23fd118Syl 735a23fd118Syl } else { /* flag == 0 */ 736a23fd118Syl 737a23fd118Syl /* Disable RxDMA Intrs in the general intr mask 738a23fd118Syl * register */ 739a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 740a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 741a23fd118Syl &bar0->rxdma_int_mask); 742a23fd118Syl 743a23fd118Syl gim |= val64; 744a23fd118Syl } 745a23fd118Syl } 746a23fd118Syl 747a23fd118Syl /* MAC Interrupts */ 748a23fd118Syl /* Enabling/Disabling MAC interrupts */ 749a23fd118Syl if (mask & (XGE_HAL_TX_MAC_INTR | XGE_HAL_RX_MAC_INTR)) { 750a23fd118Syl val64 = XGE_HAL_TXMAC_INT_M | XGE_HAL_RXMAC_INT_M; 751a23fd118Syl if (flag) { 752a23fd118Syl 753a23fd118Syl gim &= ~((u64) val64); 754a23fd118Syl 755a23fd118Syl /* All MAC block error inter. are disabled for now. */ 756a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 757a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask); 758a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 759a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask); 760a23fd118Syl 761a23fd118Syl } else { /* flag == 0 */ 762a23fd118Syl 763a23fd118Syl /* Disable MAC Intrs in the general intr mask 764a23fd118Syl * register */ 765a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 766a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask); 767a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 768a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask); 769a23fd118Syl 770a23fd118Syl gim |= val64; 771a23fd118Syl } 772a23fd118Syl } 773a23fd118Syl 774a23fd118Syl /* XGXS Interrupts */ 775a23fd118Syl if (mask & (XGE_HAL_TX_XGXS_INTR | XGE_HAL_RX_XGXS_INTR)) { 776a23fd118Syl val64 = XGE_HAL_TXXGXS_INT_M | XGE_HAL_RXXGXS_INT_M; 777a23fd118Syl if (flag) { 778a23fd118Syl 779a23fd118Syl gim &= ~((u64) val64); 780a23fd118Syl /* All XGXS block error interrupts are disabled for now 781a23fd118Syl * TODO */ 782a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 783a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask); 784a23fd118Syl 785a23fd118Syl } else { /* flag == 0 */ 786a23fd118Syl 787a23fd118Syl /* Disable MC Intrs in the general intr mask register */ 788a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 789a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask); 790a23fd118Syl 791a23fd118Syl gim |= val64; 792a23fd118Syl } 793a23fd118Syl } 794a23fd118Syl 795a23fd118Syl /* Memory Controller(MC) interrupts */ 796a23fd118Syl if (mask & XGE_HAL_MC_INTR) { 797a23fd118Syl val64 = XGE_HAL_MC_INT_M; 798a23fd118Syl if (flag) { 799a23fd118Syl 800a23fd118Syl gim &= ~((u64) val64); 801a23fd118Syl 802a23fd118Syl /* Enable all MC blocks error interrupts */ 803a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 804a23fd118Syl 0x0ULL, &bar0->mc_int_mask); 805a23fd118Syl 806a23fd118Syl } else { /* flag == 0 */ 807a23fd118Syl 808a23fd118Syl /* Disable MC Intrs in the general intr mask 809a23fd118Syl * register */ 810a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 811a23fd118Syl XGE_HAL_ALL_INTRS_DIS, &bar0->mc_int_mask); 812a23fd118Syl 813a23fd118Syl gim |= val64; 814a23fd118Syl } 815a23fd118Syl } 816a23fd118Syl 817a23fd118Syl 818a23fd118Syl /* Tx traffic interrupts */ 819a23fd118Syl if (mask & XGE_HAL_TX_TRAFFIC_INTR) { 820a23fd118Syl val64 = XGE_HAL_TXTRAFFIC_INT_M; 821a23fd118Syl if (flag) { 822a23fd118Syl 823a23fd118Syl gim &= ~((u64) val64); 824a23fd118Syl 825a23fd118Syl /* Enable all the Tx side interrupts */ 826a23fd118Syl /* '0' Enables all 64 TX interrupt levels. */ 827a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0, 828a23fd118Syl &bar0->tx_traffic_mask); 829a23fd118Syl 830a23fd118Syl } else { /* flag == 0 */ 831a23fd118Syl 832a23fd118Syl /* Disable Tx Traffic Intrs in the general intr mask 833a23fd118Syl * register. */ 834a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 835a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 836a23fd118Syl &bar0->tx_traffic_mask); 837a23fd118Syl gim |= val64; 838a23fd118Syl } 839a23fd118Syl } 840a23fd118Syl 841a23fd118Syl /* Rx traffic interrupts */ 842a23fd118Syl if (mask & XGE_HAL_RX_TRAFFIC_INTR) { 843a23fd118Syl val64 = XGE_HAL_RXTRAFFIC_INT_M; 844a23fd118Syl if (flag) { 845a23fd118Syl gim &= ~((u64) val64); 846a23fd118Syl /* '0' Enables all 8 RX interrupt levels. */ 847a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0, 848a23fd118Syl &bar0->rx_traffic_mask); 849a23fd118Syl 850a23fd118Syl } else { /* flag == 0 */ 851a23fd118Syl 852a23fd118Syl /* Disable Rx Traffic Intrs in the general intr mask 853a23fd118Syl * register. 854a23fd118Syl */ 855a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 856a23fd118Syl XGE_HAL_ALL_INTRS_DIS, 857a23fd118Syl &bar0->rx_traffic_mask); 858a23fd118Syl 859a23fd118Syl gim |= val64; 860a23fd118Syl } 861a23fd118Syl } 862a23fd118Syl 863a23fd118Syl /* Sched Timer interrupt */ 864a23fd118Syl if (mask & XGE_HAL_SCHED_INTR) { 865a23fd118Syl if (flag) { 866a23fd118Syl temp64 = xge_os_pio_mem_read64(hldev->pdev, 867a23fd118Syl hldev->regh0, &bar0->txpic_int_mask); 868a23fd118Syl temp64 &= ~XGE_HAL_TXPIC_INT_SCHED_INTR; 869a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 870a23fd118Syl temp64, &bar0->txpic_int_mask); 871a23fd118Syl 872a23fd118Syl xge_hal_device_sched_timer(hldev, 873a23fd118Syl hldev->config.sched_timer_us, 874a23fd118Syl hldev->config.sched_timer_one_shot); 875a23fd118Syl } else { 876a23fd118Syl temp64 = xge_os_pio_mem_read64(hldev->pdev, 877a23fd118Syl hldev->regh0, &bar0->txpic_int_mask); 878a23fd118Syl temp64 |= XGE_HAL_TXPIC_INT_SCHED_INTR; 879a23fd118Syl 880a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 881a23fd118Syl temp64, &bar0->txpic_int_mask); 882a23fd118Syl 883a23fd118Syl xge_hal_device_sched_timer(hldev, 884a23fd118Syl XGE_HAL_SCHED_TIMER_DISABLED, 885a23fd118Syl XGE_HAL_SCHED_TIMER_ON_SHOT_ENABLE); 886a23fd118Syl } 887a23fd118Syl } 888a23fd118Syl 889a23fd118Syl if (gim != gim_saved) { 890a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, gim, 891a23fd118Syl &bar0->general_int_mask); 8928347601bSyl xge_debug_device(XGE_TRACE, "general_int_mask updated " 8938347601bSyl XGE_OS_LLXFMT" => "XGE_OS_LLXFMT, 894a23fd118Syl (unsigned long long)gim_saved, (unsigned long long)gim); 895a23fd118Syl } 896a23fd118Syl } 897a23fd118Syl 8988347601bSyl /* 8998347601bSyl * __hal_device_bimodal_configure 9008347601bSyl * @hldev: HAL device handle. 9018347601bSyl * 9028347601bSyl * Bimodal parameters initialization. 9038347601bSyl */ 9048347601bSyl static void 9058347601bSyl __hal_device_bimodal_configure(xge_hal_device_t *hldev) 9068347601bSyl { 9078347601bSyl int i; 9088347601bSyl 9098347601bSyl for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { 9108347601bSyl xge_hal_tti_config_t *tti; 9118347601bSyl xge_hal_rti_config_t *rti; 9128347601bSyl 9138347601bSyl if (!hldev->config.ring.queue[i].configured) 9148347601bSyl continue; 9158347601bSyl rti = &hldev->config.ring.queue[i].rti; 9168347601bSyl tti = &hldev->bimodal_tti[i]; 9178347601bSyl 9188347601bSyl tti->enabled = 1; 9198347601bSyl tti->urange_a = hldev->bimodal_urange_a_en * 10; 9208347601bSyl tti->urange_b = 20; 9218347601bSyl tti->urange_c = 30; 9228347601bSyl tti->ufc_a = hldev->bimodal_urange_a_en * 8; 9238347601bSyl tti->ufc_b = 16; 9248347601bSyl tti->ufc_c = 32; 9258347601bSyl tti->ufc_d = 64; 9268347601bSyl tti->timer_val_us = hldev->bimodal_timer_val_us; 9278347601bSyl tti->timer_ac_en = 1; 9288347601bSyl tti->timer_ci_en = 0; 9298347601bSyl 9308347601bSyl rti->urange_a = 10; 9318347601bSyl rti->urange_b = 20; 9328347601bSyl rti->urange_c = 30; 9338347601bSyl rti->ufc_a = 1; /* <= for netpipe type of tests */ 9348347601bSyl rti->ufc_b = 4; 9358347601bSyl rti->ufc_c = 4; 9368347601bSyl rti->ufc_d = 4; /* <= 99% of a bandwidth traffic counts here */ 9378347601bSyl rti->timer_ac_en = 1; 9388347601bSyl rti->timer_val_us = 5; /* for optimal bus efficiency usage */ 9398347601bSyl } 9408347601bSyl } 9418347601bSyl 9428347601bSyl /* 9438347601bSyl * __hal_device_tti_apply 9448347601bSyl * @hldev: HAL device handle. 9458347601bSyl * 9468347601bSyl * apply TTI configuration. 9478347601bSyl */ 9488347601bSyl static xge_hal_status_e 9498347601bSyl __hal_device_tti_apply(xge_hal_device_t *hldev, xge_hal_tti_config_t *tti, 9508347601bSyl int num, int runtime) 9518347601bSyl { 9528347601bSyl u64 val64, data1 = 0, data2 = 0; 9538347601bSyl xge_hal_pci_bar0_t *bar0; 9548347601bSyl 9558347601bSyl if (runtime) 9568347601bSyl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 9578347601bSyl else 9588347601bSyl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 9598347601bSyl 9608347601bSyl if (tti->timer_val_us) { 9618347601bSyl unsigned int tx_interval; 9628347601bSyl 9638347601bSyl if (hldev->config.pci_freq_mherz) { 9648347601bSyl tx_interval = hldev->config.pci_freq_mherz * 9658347601bSyl tti->timer_val_us / 64; 9668347601bSyl tx_interval = 9678347601bSyl __hal_fix_time_ival_herc(hldev, 9688347601bSyl tx_interval); 9698347601bSyl } else { 9708347601bSyl tx_interval = tti->timer_val_us; 9718347601bSyl } 9728347601bSyl data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_VAL(tx_interval); 9738347601bSyl if (tti->timer_ac_en) { 9748347601bSyl data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_AC_EN; 9758347601bSyl } 9768347601bSyl if (tti->timer_ci_en) { 9778347601bSyl data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_CI_EN; 9788347601bSyl } 9798347601bSyl 9808347601bSyl if (!runtime) { 9818347601bSyl xge_debug_device(XGE_TRACE, "TTI[%d] timer enabled to %d, ci %s", 9828347601bSyl num, tx_interval, tti->timer_ci_en ? 9838347601bSyl "enabled": "disabled"); 9848347601bSyl } 9858347601bSyl } 9868347601bSyl 9878347601bSyl if (tti->urange_a || 9888347601bSyl tti->urange_b || 9898347601bSyl tti->urange_c || 9908347601bSyl tti->ufc_a || 9918347601bSyl tti->ufc_b || 9928347601bSyl tti->ufc_c || 9938347601bSyl tti->ufc_d ) { 9948347601bSyl data1 |= XGE_HAL_TTI_DATA1_MEM_TX_URNG_A(tti->urange_a) | 9958347601bSyl XGE_HAL_TTI_DATA1_MEM_TX_URNG_B(tti->urange_b) | 9968347601bSyl XGE_HAL_TTI_DATA1_MEM_TX_URNG_C(tti->urange_c); 9978347601bSyl 9988347601bSyl data2 |= XGE_HAL_TTI_DATA2_MEM_TX_UFC_A(tti->ufc_a) | 9998347601bSyl XGE_HAL_TTI_DATA2_MEM_TX_UFC_B(tti->ufc_b) | 10008347601bSyl XGE_HAL_TTI_DATA2_MEM_TX_UFC_C(tti->ufc_c) | 10018347601bSyl XGE_HAL_TTI_DATA2_MEM_TX_UFC_D(tti->ufc_d); 10028347601bSyl } 10038347601bSyl 10047eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 10057eced415Sxw data1, &bar0->tti_data1_mem); 10067eced415Sxw (void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 10077eced415Sxw &bar0->tti_data1_mem); 10087eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 10097eced415Sxw data2, &bar0->tti_data2_mem); 10107eced415Sxw (void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 10117eced415Sxw &bar0->tti_data2_mem); 10128347601bSyl xge_os_wmb(); 10138347601bSyl 10148347601bSyl val64 = XGE_HAL_TTI_CMD_MEM_WE | XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD | 10158347601bSyl XGE_HAL_TTI_CMD_MEM_OFFSET(num); 10168347601bSyl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 10178347601bSyl &bar0->tti_command_mem); 10188347601bSyl 10198347601bSyl if (!runtime && __hal_device_register_poll(hldev, &bar0->tti_command_mem, 10208347601bSyl 0, XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD, 10218347601bSyl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 10228347601bSyl /* upper layer may require to repeat */ 10238347601bSyl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 10248347601bSyl } 10258347601bSyl 10268347601bSyl if (!runtime) { 10278347601bSyl xge_debug_device(XGE_TRACE, "TTI[%d] configured: tti_data1_mem 0x" 10288347601bSyl XGE_OS_LLXFMT, num, 10298347601bSyl (unsigned long long)xge_os_pio_mem_read64(hldev->pdev, 10308347601bSyl hldev->regh0, &bar0->tti_data1_mem)); 10318347601bSyl } 10328347601bSyl 10338347601bSyl return XGE_HAL_OK; 10348347601bSyl } 10358347601bSyl 10368347601bSyl /* 10378347601bSyl * __hal_device_tti_configure 10388347601bSyl * @hldev: HAL device handle. 10398347601bSyl * 10408347601bSyl * TTI Initialization. 10418347601bSyl * Initialize Transmit Traffic Interrupt Scheme. 10428347601bSyl */ 10438347601bSyl static xge_hal_status_e 10448347601bSyl __hal_device_tti_configure(xge_hal_device_t *hldev, int runtime) 10458347601bSyl { 10468347601bSyl int i; 10478347601bSyl 10488347601bSyl for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) { 10498347601bSyl int j; 10508347601bSyl 10518347601bSyl if (!hldev->config.fifo.queue[i].configured) 10528347601bSyl continue; 10538347601bSyl 10548347601bSyl for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) { 10558347601bSyl xge_hal_status_e status; 10568347601bSyl 10578347601bSyl if (!hldev->config.fifo.queue[i].tti[j].enabled) 10588347601bSyl continue; 10598347601bSyl 10608347601bSyl /* at least some TTI enabled. Record it. */ 10618347601bSyl hldev->tti_enabled = 1; 10628347601bSyl 10638347601bSyl status = __hal_device_tti_apply(hldev, 10648347601bSyl &hldev->config.fifo.queue[i].tti[j], 10658347601bSyl i * XGE_HAL_MAX_FIFO_TTI_NUM + j, runtime); 10668347601bSyl if (status != XGE_HAL_OK) 10678347601bSyl return status; 10688347601bSyl } 10698347601bSyl } 10708347601bSyl 10718347601bSyl /* processing bimodal TTIs */ 10728347601bSyl for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { 10738347601bSyl xge_hal_status_e status; 10748347601bSyl 10758347601bSyl if (!hldev->bimodal_tti[i].enabled) 10768347601bSyl continue; 10778347601bSyl 10788347601bSyl /* at least some bimodal TTI enabled. Record it. */ 10798347601bSyl hldev->tti_enabled = 1; 10808347601bSyl 10818347601bSyl status = __hal_device_tti_apply(hldev, &hldev->bimodal_tti[i], 10828347601bSyl XGE_HAL_MAX_FIFO_TTI_RING_0 + i, runtime); 10838347601bSyl if (status != XGE_HAL_OK) 10848347601bSyl return status; 10858347601bSyl 10868347601bSyl } 10878347601bSyl 10888347601bSyl return XGE_HAL_OK; 10898347601bSyl } 10908347601bSyl 1091a23fd118Syl /* 1092a23fd118Syl * __hal_device_rti_configure 1093a23fd118Syl * @hldev: HAL device handle. 1094a23fd118Syl * 1095a23fd118Syl * RTI Initialization. 1096a23fd118Syl * Initialize Receive Traffic Interrupt Scheme. 1097a23fd118Syl */ 10988347601bSyl xge_hal_status_e 1099a23fd118Syl __hal_device_rti_configure(xge_hal_device_t *hldev, int runtime) 1100a23fd118Syl { 1101a23fd118Syl xge_hal_pci_bar0_t *bar0; 1102a23fd118Syl u64 val64, data1 = 0, data2 = 0; 1103a23fd118Syl int i; 1104a23fd118Syl 11058347601bSyl if (runtime) { 11068347601bSyl /* 11078347601bSyl * we don't want to re-configure RTI in case when 11088347601bSyl * bimodal interrupts are in use. Instead reconfigure TTI 11098347601bSyl * with new RTI values. 11108347601bSyl */ 11118347601bSyl if (hldev->config.bimodal_interrupts) { 11128347601bSyl __hal_device_bimodal_configure(hldev); 11138347601bSyl return __hal_device_tti_configure(hldev, 1); 11148347601bSyl } 1115a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 11168347601bSyl } else 1117a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1118a23fd118Syl 1119a23fd118Syl for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) { 1120a23fd118Syl xge_hal_rti_config_t *rti = &hldev->config.ring.queue[i].rti; 1121a23fd118Syl 1122a23fd118Syl if (!hldev->config.ring.queue[i].configured) 1123a23fd118Syl continue; 1124a23fd118Syl 1125a23fd118Syl if (rti->timer_val_us) { 1126a23fd118Syl unsigned int rx_interval; 1127a23fd118Syl 1128a23fd118Syl if (hldev->config.pci_freq_mherz) { 1129a23fd118Syl rx_interval = hldev->config.pci_freq_mherz * 1130a23fd118Syl rti->timer_val_us / 8; 1131a23fd118Syl rx_interval = 1132a23fd118Syl __hal_fix_time_ival_herc(hldev, 1133a23fd118Syl rx_interval); 1134a23fd118Syl } else { 1135a23fd118Syl rx_interval = rti->timer_val_us; 1136a23fd118Syl } 1137a23fd118Syl data1 |=XGE_HAL_RTI_DATA1_MEM_RX_TIMER_VAL(rx_interval); 1138a23fd118Syl if (rti->timer_ac_en) { 1139a23fd118Syl data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_AC_EN; 1140a23fd118Syl } 1141a23fd118Syl data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_CI_EN; 1142a23fd118Syl } 1143a23fd118Syl 1144a23fd118Syl if (rti->urange_a || 1145a23fd118Syl rti->urange_b || 1146a23fd118Syl rti->urange_c || 1147a23fd118Syl rti->ufc_a || 1148a23fd118Syl rti->ufc_b || 1149a23fd118Syl rti->ufc_c || 1150a23fd118Syl rti->ufc_d) { 1151a23fd118Syl data1 |=XGE_HAL_RTI_DATA1_MEM_RX_URNG_A(rti->urange_a) | 1152a23fd118Syl XGE_HAL_RTI_DATA1_MEM_RX_URNG_B(rti->urange_b) | 1153a23fd118Syl XGE_HAL_RTI_DATA1_MEM_RX_URNG_C(rti->urange_c); 1154a23fd118Syl 1155a23fd118Syl data2 |= XGE_HAL_RTI_DATA2_MEM_RX_UFC_A(rti->ufc_a) | 1156a23fd118Syl XGE_HAL_RTI_DATA2_MEM_RX_UFC_B(rti->ufc_b) | 1157a23fd118Syl XGE_HAL_RTI_DATA2_MEM_RX_UFC_C(rti->ufc_c) | 1158a23fd118Syl XGE_HAL_RTI_DATA2_MEM_RX_UFC_D(rti->ufc_d); 1159a23fd118Syl } 1160a23fd118Syl 11617eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 11627eced415Sxw data1, &bar0->rti_data1_mem); 11637eced415Sxw (void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 11647eced415Sxw &bar0->rti_data1_mem); 11657eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 11667eced415Sxw data2, &bar0->rti_data2_mem); 11677eced415Sxw (void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 11687eced415Sxw &bar0->rti_data2_mem); 11697eced415Sxw 1170a23fd118Syl xge_os_wmb(); 1171a23fd118Syl 1172a23fd118Syl val64 = XGE_HAL_RTI_CMD_MEM_WE | 1173a23fd118Syl XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD; 1174a23fd118Syl val64 |= XGE_HAL_RTI_CMD_MEM_OFFSET(i); 1175a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1176a23fd118Syl &bar0->rti_command_mem); 1177a23fd118Syl 1178a23fd118Syl if (!runtime && __hal_device_register_poll(hldev, 1179a23fd118Syl &bar0->rti_command_mem, 0, 1180a23fd118Syl XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD, 1181a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1182a23fd118Syl /* upper layer may require to repeat */ 1183a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1184a23fd118Syl } 1185a23fd118Syl 11868347601bSyl if (!runtime) { 11878347601bSyl xge_debug_device(XGE_TRACE, 11888347601bSyl "RTI[%d] configured: rti_data1_mem 0x"XGE_OS_LLXFMT, 11898347601bSyl i, 11908347601bSyl (unsigned long long)xge_os_pio_mem_read64(hldev->pdev, 11918347601bSyl hldev->regh0, &bar0->rti_data1_mem)); 1192a23fd118Syl } 1193a23fd118Syl } 1194a23fd118Syl 1195a23fd118Syl return XGE_HAL_OK; 1196a23fd118Syl } 1197a23fd118Syl 1198a23fd118Syl 1199a23fd118Syl /* Constants to be programmed into the Xena's registers to configure 1200a23fd118Syl * the XAUI. */ 1201a23fd118Syl static u64 default_xena_mdio_cfg[] = { 1202a23fd118Syl /* Reset PMA PLL */ 1203a23fd118Syl 0xC001010000000000ULL, 0xC0010100000000E0ULL, 1204a23fd118Syl 0xC0010100008000E4ULL, 1205a23fd118Syl /* Remove Reset from PMA PLL */ 1206a23fd118Syl 0xC001010000000000ULL, 0xC0010100000000E0ULL, 1207a23fd118Syl 0xC0010100000000E4ULL, 1208a23fd118Syl END_SIGN 1209a23fd118Syl }; 1210a23fd118Syl 1211a23fd118Syl static u64 default_herc_mdio_cfg[] = { 1212a23fd118Syl END_SIGN 1213a23fd118Syl }; 1214a23fd118Syl 1215a23fd118Syl static u64 default_xena_dtx_cfg[] = { 1216a23fd118Syl 0x8000051500000000ULL, 0x80000515000000E0ULL, 1217a23fd118Syl 0x80000515D93500E4ULL, 0x8001051500000000ULL, 1218a23fd118Syl 0x80010515000000E0ULL, 0x80010515001E00E4ULL, 1219a23fd118Syl 0x8002051500000000ULL, 0x80020515000000E0ULL, 1220a23fd118Syl 0x80020515F21000E4ULL, 1221a23fd118Syl /* Set PADLOOPBACKN */ 1222a23fd118Syl 0x8002051500000000ULL, 0x80020515000000E0ULL, 1223a23fd118Syl 0x80020515B20000E4ULL, 0x8003051500000000ULL, 1224a23fd118Syl 0x80030515000000E0ULL, 0x80030515B20000E4ULL, 1225a23fd118Syl 0x8004051500000000ULL, 0x80040515000000E0ULL, 1226a23fd118Syl 0x80040515B20000E4ULL, 0x8005051500000000ULL, 1227a23fd118Syl 0x80050515000000E0ULL, 0x80050515B20000E4ULL, 1228a23fd118Syl SWITCH_SIGN, 1229a23fd118Syl /* Remove PADLOOPBACKN */ 1230a23fd118Syl 0x8002051500000000ULL, 0x80020515000000E0ULL, 1231a23fd118Syl 0x80020515F20000E4ULL, 0x8003051500000000ULL, 1232a23fd118Syl 0x80030515000000E0ULL, 0x80030515F20000E4ULL, 1233a23fd118Syl 0x8004051500000000ULL, 0x80040515000000E0ULL, 1234a23fd118Syl 0x80040515F20000E4ULL, 0x8005051500000000ULL, 1235a23fd118Syl 0x80050515000000E0ULL, 0x80050515F20000E4ULL, 1236a23fd118Syl END_SIGN 1237a23fd118Syl }; 1238a23fd118Syl 1239a23fd118Syl /* 1240a23fd118Syl static u64 default_herc_dtx_cfg[] = { 1241a23fd118Syl 0x80000515BA750000ULL, 0x80000515BA7500E0ULL, 1242a23fd118Syl 0x80000515BA750004ULL, 0x80000515BA7500E4ULL, 1243a23fd118Syl 0x80010515003F0000ULL, 0x80010515003F00E0ULL, 1244a23fd118Syl 0x80010515003F0004ULL, 0x80010515003F00E4ULL, 1245a23fd118Syl 0x80020515F2100000ULL, 0x80020515F21000E0ULL, 1246a23fd118Syl 0x80020515F2100004ULL, 0x80020515F21000E4ULL, 1247a23fd118Syl END_SIGN 1248a23fd118Syl }; 1249a23fd118Syl */ 1250a23fd118Syl 1251a23fd118Syl static u64 default_herc_dtx_cfg[] = { 1252a23fd118Syl 0x8000051536750000ULL, 0x80000515367500E0ULL, 1253a23fd118Syl 0x8000051536750004ULL, 0x80000515367500E4ULL, 1254a23fd118Syl 1255a23fd118Syl 0x80010515003F0000ULL, 0x80010515003F00E0ULL, 1256a23fd118Syl 0x80010515003F0004ULL, 0x80010515003F00E4ULL, 1257a23fd118Syl 1258a23fd118Syl 0x801205150D440000ULL, 0x801205150D4400E0ULL, 1259a23fd118Syl 0x801205150D440004ULL, 0x801205150D4400E4ULL, 1260a23fd118Syl 1261a23fd118Syl 0x80020515F2100000ULL, 0x80020515F21000E0ULL, 1262a23fd118Syl 0x80020515F2100004ULL, 0x80020515F21000E4ULL, 1263a23fd118Syl END_SIGN 1264a23fd118Syl }; 1265a23fd118Syl 12667eced415Sxw 12677eced415Sxw void 12687eced415Sxw __hal_serial_mem_write64(xge_hal_device_t *hldev, u64 value, u64 *reg) 12697eced415Sxw { 12707eced415Sxw __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 12717eced415Sxw (u32)(value>>32), reg); 12727eced415Sxw xge_os_wmb(); 12737eced415Sxw __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, 12747eced415Sxw (u32)value, reg); 12757eced415Sxw xge_os_wmb(); 12767eced415Sxw xge_os_mdelay(1); 12777eced415Sxw } 12787eced415Sxw 12797eced415Sxw u64 12807eced415Sxw __hal_serial_mem_read64(xge_hal_device_t *hldev, u64 *reg) 12817eced415Sxw { 12827eced415Sxw u64 val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 12837eced415Sxw reg); 12847eced415Sxw xge_os_mdelay(1); 12857eced415Sxw return val64; 12867eced415Sxw } 12877eced415Sxw 1288a23fd118Syl /* 1289a23fd118Syl * __hal_device_xaui_configure 1290a23fd118Syl * @hldev: HAL device handle. 1291a23fd118Syl * 1292a23fd118Syl * Configure XAUI Interface of Xena. 1293a23fd118Syl * 1294a23fd118Syl * To Configure the Xena's XAUI, one has to write a series 1295a23fd118Syl * of 64 bit values into two registers in a particular 1296a23fd118Syl * sequence. Hence a macro 'SWITCH_SIGN' has been defined 1297a23fd118Syl * which will be defined in the array of configuration values 1298a23fd118Syl * (default_dtx_cfg & default_mdio_cfg) at appropriate places 1299a23fd118Syl * to switch writing from one regsiter to another. We continue 1300a23fd118Syl * writing these values until we encounter the 'END_SIGN' macro. 1301a23fd118Syl * For example, After making a series of 21 writes into 1302a23fd118Syl * dtx_control register the 'SWITCH_SIGN' appears and hence we 1303a23fd118Syl * start writing into mdio_control until we encounter END_SIGN. 1304a23fd118Syl */ 1305a23fd118Syl static void 1306a23fd118Syl __hal_device_xaui_configure(xge_hal_device_t *hldev) 1307a23fd118Syl { 1308a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1309a23fd118Syl int mdio_cnt = 0, dtx_cnt = 0; 1310a23fd118Syl u64 *default_dtx_cfg = NULL, *default_mdio_cfg = NULL; 1311a23fd118Syl 1312a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 1313a23fd118Syl default_dtx_cfg = default_xena_dtx_cfg; 1314a23fd118Syl default_mdio_cfg = default_xena_mdio_cfg; 1315a23fd118Syl } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 1316a23fd118Syl default_dtx_cfg = default_herc_dtx_cfg; 1317a23fd118Syl default_mdio_cfg = default_herc_mdio_cfg; 13187eced415Sxw } else { 13198347601bSyl xge_assert(default_dtx_cfg); 13207eced415Sxw return; 13217eced415Sxw } 1322a23fd118Syl 1323a23fd118Syl do { 1324a23fd118Syl dtx_cfg: 1325a23fd118Syl while (default_dtx_cfg[dtx_cnt] != END_SIGN) { 1326a23fd118Syl if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { 1327a23fd118Syl dtx_cnt++; 1328a23fd118Syl goto mdio_cfg; 1329a23fd118Syl } 13307eced415Sxw __hal_serial_mem_write64(hldev, default_dtx_cfg[dtx_cnt], 13317eced415Sxw &bar0->dtx_control); 1332a23fd118Syl dtx_cnt++; 1333a23fd118Syl } 1334a23fd118Syl mdio_cfg: 1335a23fd118Syl while (default_mdio_cfg[mdio_cnt] != END_SIGN) { 1336a23fd118Syl if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { 1337a23fd118Syl mdio_cnt++; 1338a23fd118Syl goto dtx_cfg; 1339a23fd118Syl } 13407eced415Sxw __hal_serial_mem_write64(hldev, default_mdio_cfg[mdio_cnt], 13417eced415Sxw &bar0->mdio_control); 1342a23fd118Syl mdio_cnt++; 1343a23fd118Syl } 1344a23fd118Syl } while ( !((default_dtx_cfg[dtx_cnt] == END_SIGN) && 1345a23fd118Syl (default_mdio_cfg[mdio_cnt] == END_SIGN)) ); 1346a23fd118Syl 1347a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "XAUI interface configured"); 1348a23fd118Syl } 1349a23fd118Syl 1350a23fd118Syl /* 1351a23fd118Syl * __hal_device_mac_link_util_set 1352a23fd118Syl * @hldev: HAL device handle. 1353a23fd118Syl * 1354a23fd118Syl * Set sampling rate to calculate link utilization. 1355a23fd118Syl */ 1356a23fd118Syl static void 1357a23fd118Syl __hal_device_mac_link_util_set(xge_hal_device_t *hldev) 1358a23fd118Syl { 1359a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1360a23fd118Syl u64 val64; 1361a23fd118Syl 1362a23fd118Syl val64 = XGE_HAL_MAC_TX_LINK_UTIL_VAL( 1363a23fd118Syl hldev->config.mac.tmac_util_period) | 1364a23fd118Syl XGE_HAL_MAC_RX_LINK_UTIL_VAL( 1365a23fd118Syl hldev->config.mac.rmac_util_period); 1366a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1367a23fd118Syl &bar0->mac_link_util); 1368a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 1369a23fd118Syl "bandwidth link utilization configured"); 1370a23fd118Syl } 1371a23fd118Syl 1372a23fd118Syl /* 1373a23fd118Syl * __hal_device_set_swapper 1374a23fd118Syl * @hldev: HAL device handle. 1375a23fd118Syl * 1376a23fd118Syl * Set the Xframe's byte "swapper" in accordance with 1377a23fd118Syl * endianness of the host. 1378a23fd118Syl */ 1379a23fd118Syl xge_hal_status_e 1380a23fd118Syl __hal_device_set_swapper(xge_hal_device_t *hldev) 1381a23fd118Syl { 1382a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1383a23fd118Syl u64 val64; 1384a23fd118Syl 1385a23fd118Syl /* 1386a23fd118Syl * from 32bit errarta: 1387a23fd118Syl * 1388a23fd118Syl * The SWAPPER_CONTROL register determines how the adapter accesses 1389a23fd118Syl * host memory as well as how it responds to read and write requests 1390a23fd118Syl * from the host system. Writes to this register should be performed 1391a23fd118Syl * carefully, since the byte swappers could reverse the order of bytes. 1392a23fd118Syl * When configuring this register keep in mind that writes to the PIF 1393a23fd118Syl * read and write swappers could reverse the order of the upper and 1394a23fd118Syl * lower 32-bit words. This means that the driver may have to write 1395a23fd118Syl * to the upper 32 bits of the SWAPPER_CONTROL twice in order to 1396a23fd118Syl * configure the entire register. */ 1397a23fd118Syl 1398a23fd118Syl /* 1399a23fd118Syl * The device by default set to a big endian format, so a big endian 1400a23fd118Syl * driver need not set anything. 1401a23fd118Syl */ 1402a23fd118Syl 1403a23fd118Syl #if defined(XGE_HAL_CUSTOM_HW_SWAPPER) 1404a23fd118Syl 1405a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1406a23fd118Syl 0xffffffffffffffffULL, &bar0->swapper_ctrl); 1407a23fd118Syl 1408a23fd118Syl val64 = XGE_HAL_CUSTOM_HW_SWAPPER; 1409a23fd118Syl 1410a23fd118Syl xge_os_wmb(); 1411a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1412a23fd118Syl &bar0->swapper_ctrl); 1413a23fd118Syl 14148347601bSyl xge_debug_device(XGE_TRACE, "using custom HW swapper 0x"XGE_OS_LLXFMT, 1415a23fd118Syl (unsigned long long)val64); 1416a23fd118Syl 1417a23fd118Syl #elif !defined(XGE_OS_HOST_BIG_ENDIAN) 1418a23fd118Syl 1419a23fd118Syl /* 1420a23fd118Syl * Initially we enable all bits to make it accessible by the driver, 1421a23fd118Syl * then we selectively enable only those bits that we want to set. 1422a23fd118Syl * i.e. force swapper to swap for the first time since second write 1423a23fd118Syl * will overwrite with the final settings. 1424a23fd118Syl * 1425a23fd118Syl * Use only for little endian platforms. 1426a23fd118Syl */ 1427a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1428a23fd118Syl 0xffffffffffffffffULL, &bar0->swapper_ctrl); 1429a23fd118Syl xge_os_wmb(); 1430a23fd118Syl val64 = (XGE_HAL_SWAPPER_CTRL_PIF_R_FE | 1431a23fd118Syl XGE_HAL_SWAPPER_CTRL_PIF_R_SE | 1432a23fd118Syl XGE_HAL_SWAPPER_CTRL_PIF_W_FE | 1433a23fd118Syl XGE_HAL_SWAPPER_CTRL_PIF_W_SE | 1434a23fd118Syl XGE_HAL_SWAPPER_CTRL_RTH_FE | 1435a23fd118Syl XGE_HAL_SWAPPER_CTRL_RTH_SE | 1436a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXP_FE | 1437a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXP_SE | 1438a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXD_R_FE | 1439a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXD_R_SE | 1440a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXD_W_FE | 1441a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXD_W_SE | 1442a23fd118Syl XGE_HAL_SWAPPER_CTRL_TXF_R_FE | 1443a23fd118Syl XGE_HAL_SWAPPER_CTRL_RXD_R_FE | 1444a23fd118Syl XGE_HAL_SWAPPER_CTRL_RXD_R_SE | 1445a23fd118Syl XGE_HAL_SWAPPER_CTRL_RXD_W_FE | 1446a23fd118Syl XGE_HAL_SWAPPER_CTRL_RXD_W_SE | 1447a23fd118Syl XGE_HAL_SWAPPER_CTRL_RXF_W_FE | 1448a23fd118Syl XGE_HAL_SWAPPER_CTRL_XMSI_FE | 1449a23fd118Syl XGE_HAL_SWAPPER_CTRL_STATS_FE | XGE_HAL_SWAPPER_CTRL_STATS_SE); 14507eced415Sxw 14517eced415Sxw /* 1452a23fd118Syl if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 1453a23fd118Syl val64 |= XGE_HAL_SWAPPER_CTRL_XMSI_SE; 1454a23fd118Syl } */ 1455a23fd118Syl __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)val64, 1456a23fd118Syl &bar0->swapper_ctrl); 1457a23fd118Syl xge_os_wmb(); 1458a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), 1459a23fd118Syl &bar0->swapper_ctrl); 1460a23fd118Syl xge_os_wmb(); 1461a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32), 1462a23fd118Syl &bar0->swapper_ctrl); 1463a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "using little endian set"); 1464a23fd118Syl #endif 1465a23fd118Syl 1466a23fd118Syl /* Verifying if endian settings are accurate by reading a feedback 1467a23fd118Syl * register. */ 1468a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1469a23fd118Syl &bar0->pif_rd_swapper_fb); 1470a23fd118Syl if (val64 != XGE_HAL_IF_RD_SWAPPER_FB) { 14718347601bSyl xge_debug_device(XGE_ERR, "pif_rd_swapper_fb read "XGE_OS_LLXFMT, 1472a23fd118Syl (unsigned long long) val64); 1473a23fd118Syl return XGE_HAL_ERR_SWAPPER_CTRL; 1474a23fd118Syl } 1475a23fd118Syl 1476a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "be/le swapper enabled"); 1477a23fd118Syl 1478a23fd118Syl return XGE_HAL_OK; 1479a23fd118Syl } 1480a23fd118Syl 1481a23fd118Syl /* 1482a23fd118Syl * __hal_device_rts_mac_configure - Configure RTS steering based on 1483a23fd118Syl * destination mac address. 1484a23fd118Syl * @hldev: HAL device handle. 1485a23fd118Syl * 1486a23fd118Syl */ 1487a23fd118Syl xge_hal_status_e 1488a23fd118Syl __hal_device_rts_mac_configure(xge_hal_device_t *hldev) 1489a23fd118Syl { 1490a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1491a23fd118Syl u64 val64; 1492a23fd118Syl 1493a23fd118Syl if (!hldev->config.rts_mac_en) { 1494a23fd118Syl return XGE_HAL_OK; 1495a23fd118Syl } 1496a23fd118Syl 1497a23fd118Syl /* 1498a23fd118Syl * Set the receive traffic steering mode from default(classic) 1499a23fd118Syl * to enhanced. 1500a23fd118Syl */ 1501a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1502a23fd118Syl &bar0->rts_ctrl); 1503a23fd118Syl val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 1504a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1505a23fd118Syl val64, &bar0->rts_ctrl); 1506a23fd118Syl return XGE_HAL_OK; 1507a23fd118Syl } 1508a23fd118Syl 15097eced415Sxw /* 15107eced415Sxw * __hal_device_rts_port_configure - Configure RTS steering based on 15117eced415Sxw * destination or source port number. 15127eced415Sxw * @hldev: HAL device handle. 15137eced415Sxw * 15147eced415Sxw */ 15157eced415Sxw xge_hal_status_e 15167eced415Sxw __hal_device_rts_port_configure(xge_hal_device_t *hldev) 15177eced415Sxw { 15187eced415Sxw xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 15197eced415Sxw u64 val64; 15207eced415Sxw int rnum; 15217eced415Sxw 15227eced415Sxw if (!hldev->config.rts_port_en) { 15237eced415Sxw return XGE_HAL_OK; 15247eced415Sxw } 15257eced415Sxw 15267eced415Sxw /* 15277eced415Sxw * Set the receive traffic steering mode from default(classic) 15287eced415Sxw * to enhanced. 15297eced415Sxw */ 15307eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 15317eced415Sxw &bar0->rts_ctrl); 15327eced415Sxw val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 15337eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 15347eced415Sxw val64, &bar0->rts_ctrl); 15357eced415Sxw 15367eced415Sxw /* 15377eced415Sxw * Initiate port steering according to per-ring configuration 15387eced415Sxw */ 15397eced415Sxw for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) { 15407eced415Sxw int pnum; 15417eced415Sxw xge_hal_ring_queue_t *queue = &hldev->config.ring.queue[rnum]; 15427eced415Sxw 15437eced415Sxw if (!queue->configured || queue->rts_port_en) 15447eced415Sxw continue; 15457eced415Sxw 15467eced415Sxw for (pnum = 0; pnum < XGE_HAL_MAX_STEERABLE_PORTS; pnum++) { 15477eced415Sxw xge_hal_rts_port_t *port = &queue->rts_ports[pnum]; 15487eced415Sxw 15497eced415Sxw /* 15507eced415Sxw * Skip and clear empty ports 15517eced415Sxw */ 15527eced415Sxw if (!port->num) { 15537eced415Sxw /* 15547eced415Sxw * Clear CAM memory 15557eced415Sxw */ 15567eced415Sxw xge_os_pio_mem_write64(hldev->pdev, 15577eced415Sxw hldev->regh0, 0ULL, 15587eced415Sxw &bar0->rts_pn_cam_data); 15597eced415Sxw 15607eced415Sxw val64 = BIT(7) | BIT(15); 15617eced415Sxw } else { 15627eced415Sxw /* 15637eced415Sxw * Assign new Port values according 15647eced415Sxw * to configuration 15657eced415Sxw */ 15667eced415Sxw val64 = vBIT(port->num,8,16) | 15677eced415Sxw vBIT(rnum,37,3) | BIT(63); 15687eced415Sxw if (port->src) 15697eced415Sxw val64 = BIT(47); 15707eced415Sxw if (!port->udp) 15717eced415Sxw val64 = BIT(7); 15727eced415Sxw xge_os_pio_mem_write64(hldev->pdev, 15737eced415Sxw hldev->regh0, val64, 15747eced415Sxw &bar0->rts_pn_cam_data); 15757eced415Sxw 15767eced415Sxw val64 = BIT(7) | BIT(15) | vBIT(pnum,24,8); 15777eced415Sxw } 15787eced415Sxw 15797eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 15807eced415Sxw val64, &bar0->rts_pn_cam_ctrl); 15817eced415Sxw 15827eced415Sxw /* poll until done */ 15837eced415Sxw if (__hal_device_register_poll(hldev, 15847eced415Sxw &bar0->rts_pn_cam_ctrl, 0, 15857eced415Sxw XGE_HAL_RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED, 15867eced415Sxw XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != 15877eced415Sxw XGE_HAL_OK) { 15887eced415Sxw /* upper layer may require to repeat */ 15897eced415Sxw return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 15907eced415Sxw } 15917eced415Sxw } 15927eced415Sxw } 15937eced415Sxw return XGE_HAL_OK; 15947eced415Sxw } 15957eced415Sxw 15968347601bSyl /* 15978347601bSyl * __hal_device_rts_qos_configure - Configure RTS steering based on 15988347601bSyl * qos. 15998347601bSyl * @hldev: HAL device handle. 16008347601bSyl * 16018347601bSyl */ 16028347601bSyl xge_hal_status_e 16038347601bSyl __hal_device_rts_qos_configure(xge_hal_device_t *hldev) 16048347601bSyl { 16058347601bSyl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 16068347601bSyl u64 val64; 16077eced415Sxw int j, rx_ring_num; 16088347601bSyl 16097eced415Sxw if (!hldev->config.rts_qos_en) { 16108347601bSyl return XGE_HAL_OK; 16118347601bSyl } 16128347601bSyl 16137eced415Sxw /* First clear the RTS_DS_MEM_DATA */ 16147eced415Sxw val64 = 0; 16157eced415Sxw for (j = 0; j < 64; j++ ) 16167eced415Sxw { 16177eced415Sxw /* First clear the value */ 16187eced415Sxw val64 = XGE_HAL_RTS_DS_MEM_DATA(0); 16198347601bSyl 16207eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 16217eced415Sxw &bar0->rts_ds_mem_data); 16228347601bSyl 16237eced415Sxw val64 = XGE_HAL_RTS_DS_MEM_CTRL_WE | 16247eced415Sxw XGE_HAL_RTS_DS_MEM_CTRL_STROBE_NEW_CMD | 16257eced415Sxw XGE_HAL_RTS_DS_MEM_CTRL_OFFSET ( j ); 16268347601bSyl 16277eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 16287eced415Sxw &bar0->rts_ds_mem_ctrl); 16298347601bSyl 16308347601bSyl 16318347601bSyl /* poll until done */ 16328347601bSyl if (__hal_device_register_poll(hldev, 16338347601bSyl &bar0->rts_ds_mem_ctrl, 0, 16348347601bSyl XGE_HAL_RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED, 16358347601bSyl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 16368347601bSyl /* upper layer may require to repeat */ 16378347601bSyl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 16388347601bSyl } 16398347601bSyl 16407eced415Sxw } 16418347601bSyl 16427eced415Sxw rx_ring_num = 0; 16437eced415Sxw for (j = 0; j < XGE_HAL_MAX_RING_NUM; j++) { 16447eced415Sxw if (hldev->config.ring.queue[j].configured) 16457eced415Sxw rx_ring_num++; 16467eced415Sxw } 16478347601bSyl 16487eced415Sxw switch (rx_ring_num) { 16497eced415Sxw case 1: 16507eced415Sxw val64 = 0x0; 16517eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 16527eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 16537eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 16547eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 16557eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 16567eced415Sxw break; 16577eced415Sxw case 2: 16587eced415Sxw val64 = 0x0001000100010001ULL; 16597eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 16607eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 16617eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 16627eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 16637eced415Sxw val64 = 0x0001000100000000ULL; 16647eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 16657eced415Sxw break; 16667eced415Sxw case 3: 16677eced415Sxw val64 = 0x0001020001020001ULL; 16687eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 16697eced415Sxw val64 = 0x0200010200010200ULL; 16707eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 16717eced415Sxw val64 = 0x0102000102000102ULL; 16727eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 16737eced415Sxw val64 = 0x0001020001020001ULL; 16747eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 16757eced415Sxw val64 = 0x0200010200000000ULL; 16767eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 16777eced415Sxw break; 16787eced415Sxw case 4: 16797eced415Sxw val64 = 0x0001020300010203ULL; 16807eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 16817eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 16827eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 16837eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 16847eced415Sxw val64 = 0x0001020300000000ULL; 16857eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 16867eced415Sxw break; 16877eced415Sxw case 5: 16887eced415Sxw val64 = 0x0001020304000102ULL; 16897eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 16907eced415Sxw val64 = 0x0304000102030400ULL; 16917eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 16927eced415Sxw val64 = 0x0102030400010203ULL; 16937eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 16947eced415Sxw val64 = 0x0400010203040001ULL; 16957eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 16967eced415Sxw val64 = 0x0203040000000000ULL; 16977eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 16987eced415Sxw break; 16997eced415Sxw case 6: 17007eced415Sxw val64 = 0x0001020304050001ULL; 17017eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 17027eced415Sxw val64 = 0x0203040500010203ULL; 17037eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 17047eced415Sxw val64 = 0x0405000102030405ULL; 17057eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 17067eced415Sxw val64 = 0x0001020304050001ULL; 17077eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 17087eced415Sxw val64 = 0x0203040500000000ULL; 17097eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 17107eced415Sxw break; 17117eced415Sxw case 7: 17127eced415Sxw val64 = 0x0001020304050600ULL; 17137eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 17147eced415Sxw val64 = 0x0102030405060001ULL; 17157eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 17167eced415Sxw val64 = 0x0203040506000102ULL; 17177eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 17187eced415Sxw val64 = 0x0304050600010203ULL; 17197eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 17207eced415Sxw val64 = 0x0405060000000000ULL; 17217eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 17227eced415Sxw break; 17237eced415Sxw case 8: 17247eced415Sxw val64 = 0x0001020304050607ULL; 17257eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0); 17267eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1); 17277eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2); 17287eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3); 17297eced415Sxw val64 = 0x0001020300000000ULL; 17307eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4); 17317eced415Sxw break; 17327eced415Sxw } 17338347601bSyl 17348347601bSyl return XGE_HAL_OK; 17358347601bSyl } 17368347601bSyl 1737a23fd118Syl /* 1738a23fd118Syl * xge__hal_device_rts_mac_enable 1739a23fd118Syl * 1740a23fd118Syl * @devh: HAL device handle. 1741a23fd118Syl * @index: index number where the MAC addr will be stored 1742a23fd118Syl * @macaddr: MAC address 1743a23fd118Syl * 1744a23fd118Syl * - Enable RTS steering for the given MAC address. This function has to be 1745a23fd118Syl * called with lock acquired. 1746a23fd118Syl * 1747a23fd118Syl * NOTE: 1748a23fd118Syl * 1. ULD has to call this function with the index value which 1749a23fd118Syl * statisfies the following condition: 1750a23fd118Syl * ring_num = (index % 8) 1751a23fd118Syl * 2.ULD also needs to make sure that the index is not 1752a23fd118Syl * occupied by any MAC address. If that index has any MAC address 1753a23fd118Syl * it will be overwritten and HAL will not check for it. 1754a23fd118Syl * 1755a23fd118Syl */ 1756a23fd118Syl xge_hal_status_e 1757a23fd118Syl xge_hal_device_rts_mac_enable(xge_hal_device_h devh, int index, macaddr_t macaddr) 1758a23fd118Syl { 17598347601bSyl int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; 1760a23fd118Syl xge_hal_status_e status; 1761a23fd118Syl 1762a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 1763a23fd118Syl 17648347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 17658347601bSyl max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; 17668347601bSyl 17678347601bSyl if ( index >= max_addr ) 1768a23fd118Syl return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 1769a23fd118Syl 1770a23fd118Syl /* 1771a23fd118Syl * Set the MAC address at the given location marked by index. 1772a23fd118Syl */ 1773a23fd118Syl status = xge_hal_device_macaddr_set(hldev, index, macaddr); 1774a23fd118Syl if (status != XGE_HAL_OK) { 1775a23fd118Syl xge_debug_device(XGE_ERR, "%s", 1776a23fd118Syl "Not able to set the mac addr"); 17778347601bSyl return status; 17788347601bSyl } 1779a23fd118Syl 17808347601bSyl return xge_hal_device_rts_section_enable(hldev, index); 1781a23fd118Syl } 1782a23fd118Syl 1783a23fd118Syl /* 1784a23fd118Syl * xge__hal_device_rts_mac_disable 1785a23fd118Syl * @hldev: HAL device handle. 1786a23fd118Syl * @index: index number where to disable the MAC addr 1787a23fd118Syl * 1788a23fd118Syl * Disable RTS Steering based on the MAC address. 1789a23fd118Syl * This function should be called with lock acquired. 1790a23fd118Syl * 1791a23fd118Syl */ 1792a23fd118Syl xge_hal_status_e 1793a23fd118Syl xge_hal_device_rts_mac_disable(xge_hal_device_h devh, int index) 1794a23fd118Syl { 1795a23fd118Syl xge_hal_status_e status; 1796a23fd118Syl u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 17978347601bSyl int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; 1798a23fd118Syl 1799a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 1800a23fd118Syl 18017eced415Sxw xge_debug_ll(XGE_TRACE, "the index value is %d ", index); 18028347601bSyl 18038347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 18048347601bSyl max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; 18058347601bSyl 18068347601bSyl if ( index >= max_addr ) 1807a23fd118Syl return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 1808a23fd118Syl 1809a23fd118Syl /* 1810a23fd118Syl * Disable MAC address @ given index location 1811a23fd118Syl */ 1812a23fd118Syl status = xge_hal_device_macaddr_set(hldev, index, macaddr); 1813a23fd118Syl if (status != XGE_HAL_OK) { 1814a23fd118Syl xge_debug_device(XGE_ERR, "%s", 1815a23fd118Syl "Not able to set the mac addr"); 1816a23fd118Syl return status; 1817a23fd118Syl } 1818a23fd118Syl 1819a23fd118Syl return XGE_HAL_OK; 1820a23fd118Syl } 1821a23fd118Syl 1822a23fd118Syl 1823a23fd118Syl /* 1824a23fd118Syl * __hal_device_rth_configure - Configure RTH for the device 1825a23fd118Syl * @hldev: HAL device handle. 1826a23fd118Syl * 1827a23fd118Syl * Using IT (Indirection Table). 1828a23fd118Syl */ 1829a23fd118Syl xge_hal_status_e 1830a23fd118Syl __hal_device_rth_it_configure(xge_hal_device_t *hldev) 1831a23fd118Syl { 1832a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1833a23fd118Syl u64 val64; 1834a23fd118Syl int rings[XGE_HAL_MAX_RING_NUM]={0}; 1835a23fd118Syl int rnum; 1836a23fd118Syl int rmax; 1837a23fd118Syl int buckets_num; 1838a23fd118Syl int bucket; 1839a23fd118Syl 1840a23fd118Syl if (!hldev->config.rth_en) { 1841a23fd118Syl return XGE_HAL_OK; 1842a23fd118Syl } 1843a23fd118Syl 1844a23fd118Syl /* 1845a23fd118Syl * Set the receive traffic steering mode from default(classic) 1846a23fd118Syl * to enhanced. 1847a23fd118Syl */ 1848a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 1849a23fd118Syl &bar0->rts_ctrl); 1850a23fd118Syl val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 1851a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1852a23fd118Syl val64, &bar0->rts_ctrl); 1853a23fd118Syl 1854a23fd118Syl buckets_num = (1 << hldev->config.rth_bucket_size); 1855a23fd118Syl 1856a23fd118Syl rmax=0; 1857a23fd118Syl for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) { 1858a23fd118Syl if (hldev->config.ring.queue[rnum].configured && 1859a23fd118Syl hldev->config.ring.queue[rnum].rth_en) 1860a23fd118Syl rings[rmax++] = rnum; 18617eced415Sxw } 1862a23fd118Syl 1863a23fd118Syl rnum = 0; 1864a23fd118Syl /* for starters: fill in all the buckets with rings "equally" */ 1865a23fd118Syl for (bucket = 0; bucket < buckets_num; bucket++) { 1866a23fd118Syl 1867a23fd118Syl if (rnum == rmax) 1868a23fd118Syl rnum = 0; 1869a23fd118Syl 1870a23fd118Syl /* write data */ 1871a23fd118Syl val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN | 1872a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_DATA(rings[rnum]); 1873a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1874a23fd118Syl &bar0->rts_rth_map_mem_data); 1875a23fd118Syl 1876a23fd118Syl /* execute */ 1877a23fd118Syl val64 = XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE | 1878a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE | 1879a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(bucket); 1880a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1881a23fd118Syl &bar0->rts_rth_map_mem_ctrl); 1882a23fd118Syl 1883a23fd118Syl /* poll until done */ 1884a23fd118Syl if (__hal_device_register_poll(hldev, 1885a23fd118Syl &bar0->rts_rth_map_mem_ctrl, 0, 1886a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE, 1887a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1888a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1889a23fd118Syl } 1890a23fd118Syl 1891a23fd118Syl rnum++; 1892a23fd118Syl } 1893a23fd118Syl 1894a23fd118Syl val64 = XGE_HAL_RTS_RTH_EN; 1895a23fd118Syl val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(hldev->config.rth_bucket_size); 18967eced415Sxw val64 |= XGE_HAL_RTS_RTH_TCP_IPV4_EN | XGE_HAL_RTS_RTH_UDP_IPV4_EN | XGE_HAL_RTS_RTH_IPV4_EN | 1897a23fd118Syl XGE_HAL_RTS_RTH_TCP_IPV6_EN |XGE_HAL_RTS_RTH_UDP_IPV6_EN | XGE_HAL_RTS_RTH_IPV6_EN | 1898a23fd118Syl XGE_HAL_RTS_RTH_TCP_IPV6_EX_EN | XGE_HAL_RTS_RTH_UDP_IPV6_EX_EN | XGE_HAL_RTS_RTH_IPV6_EX_EN; 1899a23fd118Syl 1900a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1901a23fd118Syl &bar0->rts_rth_cfg); 1902a23fd118Syl 1903a23fd118Syl xge_debug_device(XGE_TRACE, "RTH configured, bucket_size %d", 1904a23fd118Syl hldev->config.rth_bucket_size); 1905a23fd118Syl 1906a23fd118Syl return XGE_HAL_OK; 1907a23fd118Syl } 1908a23fd118Syl 1909a23fd118Syl 1910a23fd118Syl /* 1911a23fd118Syl * __hal_spdm_entry_add - Add a new entry to the SPDM table. 1912a23fd118Syl * 1913a23fd118Syl * Add a new entry to the SPDM table 1914a23fd118Syl * 1915a23fd118Syl * This function add a new entry to the SPDM table. 1916a23fd118Syl * 1917a23fd118Syl * Note: 1918a23fd118Syl * This function should be called with spdm_lock. 1919a23fd118Syl * 1920a23fd118Syl * See also: xge_hal_spdm_entry_add , xge_hal_spdm_entry_remove. 1921a23fd118Syl */ 1922a23fd118Syl static xge_hal_status_e 1923a23fd118Syl __hal_spdm_entry_add(xge_hal_device_t *hldev, xge_hal_ipaddr_t *src_ip, 1924a23fd118Syl xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, u8 is_tcp, 1925a23fd118Syl u8 is_ipv4, u8 tgt_queue, u32 jhash_value, u16 spdm_entry) 1926a23fd118Syl { 1927a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 1928a23fd118Syl u64 val64; 1929a23fd118Syl u64 spdm_line_arr[8]; 1930a23fd118Syl u8 line_no; 1931a23fd118Syl 1932a23fd118Syl /* 1933a23fd118Syl * Clear the SPDM READY bit 1934a23fd118Syl */ 19358347601bSyl val64 = XGE_HAL_RX_PIC_INT_REG_SPDM_READY; 1936a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 1937a23fd118Syl &bar0->rxpic_int_reg); 1938a23fd118Syl 1939a23fd118Syl xge_debug_device(XGE_TRACE, 19407eced415Sxw "L4 SP %x:DP %x: hash %x tgt_queue %d ", 1941a23fd118Syl l4_sp, l4_dp, jhash_value, tgt_queue); 1942a23fd118Syl 1943a23fd118Syl xge_os_memzero(&spdm_line_arr, sizeof(spdm_line_arr)); 1944a23fd118Syl 1945a23fd118Syl /* 1946a23fd118Syl * Construct the SPDM entry. 1947a23fd118Syl */ 1948a23fd118Syl spdm_line_arr[0] = vBIT(l4_sp,0,16) | 1949a23fd118Syl vBIT(l4_dp,16,32) | 1950a23fd118Syl vBIT(tgt_queue,53,3) | 1951a23fd118Syl vBIT(is_tcp,59,1) | 1952a23fd118Syl vBIT(is_ipv4,63,1); 1953a23fd118Syl 1954a23fd118Syl 1955a23fd118Syl if (is_ipv4) { 1956a23fd118Syl spdm_line_arr[1] = vBIT(src_ip->ipv4.addr,0,32) | 1957a23fd118Syl vBIT(dst_ip->ipv4.addr,32,32); 1958a23fd118Syl 1959a23fd118Syl } else { 1960a23fd118Syl xge_os_memcpy(&spdm_line_arr[1], &src_ip->ipv6.addr[0], 8); 1961a23fd118Syl xge_os_memcpy(&spdm_line_arr[2], &src_ip->ipv6.addr[1], 8); 1962a23fd118Syl xge_os_memcpy(&spdm_line_arr[3], &dst_ip->ipv6.addr[0], 8); 1963a23fd118Syl xge_os_memcpy(&spdm_line_arr[4], &dst_ip->ipv6.addr[1], 8); 1964a23fd118Syl } 1965a23fd118Syl 1966a23fd118Syl spdm_line_arr[7] = vBIT(jhash_value,0,32) | 1967a23fd118Syl BIT(63); /* entry enable bit */ 1968a23fd118Syl 1969a23fd118Syl /* 1970a23fd118Syl * Add the entry to the SPDM table 1971a23fd118Syl */ 1972a23fd118Syl for(line_no = 0; line_no < 8; line_no++) { 1973a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 1974a23fd118Syl spdm_line_arr[line_no], 1975a23fd118Syl (void *)((char *)hldev->spdm_mem_base + 1976a23fd118Syl (spdm_entry * 64) + 1977a23fd118Syl (line_no * 8))); 1978a23fd118Syl } 1979a23fd118Syl 1980a23fd118Syl /* 1981a23fd118Syl * Wait for the operation to be completed. 1982a23fd118Syl */ 1983a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1, 1984a23fd118Syl XGE_HAL_RX_PIC_INT_REG_SPDM_READY, 1985a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 1986a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 1987a23fd118Syl } 1988a23fd118Syl 1989a23fd118Syl /* 1990a23fd118Syl * Add this information to a local SPDM table. The purpose of 1991a23fd118Syl * maintaining a local SPDM table is to avoid a search in the 1992a23fd118Syl * adapter SPDM table for spdm entry lookup which is very costly 1993a23fd118Syl * in terms of time. 1994a23fd118Syl */ 1995a23fd118Syl hldev->spdm_table[spdm_entry]->in_use = 1; 1996a23fd118Syl xge_os_memcpy(&hldev->spdm_table[spdm_entry]->src_ip, src_ip, 1997a23fd118Syl sizeof(xge_hal_ipaddr_t)); 1998a23fd118Syl xge_os_memcpy(&hldev->spdm_table[spdm_entry]->dst_ip, dst_ip, 1999a23fd118Syl sizeof(xge_hal_ipaddr_t)); 2000a23fd118Syl hldev->spdm_table[spdm_entry]->l4_sp = l4_sp; 2001a23fd118Syl hldev->spdm_table[spdm_entry]->l4_dp = l4_dp; 2002a23fd118Syl hldev->spdm_table[spdm_entry]->is_tcp = is_tcp; 2003a23fd118Syl hldev->spdm_table[spdm_entry]->is_ipv4 = is_ipv4; 2004a23fd118Syl hldev->spdm_table[spdm_entry]->tgt_queue = tgt_queue; 2005a23fd118Syl hldev->spdm_table[spdm_entry]->jhash_value = jhash_value; 2006a23fd118Syl hldev->spdm_table[spdm_entry]->spdm_entry = spdm_entry; 2007a23fd118Syl 2008a23fd118Syl return XGE_HAL_OK; 2009a23fd118Syl } 2010a23fd118Syl 2011a23fd118Syl /* 2012a23fd118Syl * __hal_device_rth_spdm_configure - Configure RTH for the device 2013a23fd118Syl * @hldev: HAL device handle. 2014a23fd118Syl * 2015a23fd118Syl * Using SPDM (Socket-Pair Direct Match). 2016a23fd118Syl */ 2017a23fd118Syl xge_hal_status_e 2018a23fd118Syl __hal_device_rth_spdm_configure(xge_hal_device_t *hldev) 2019a23fd118Syl { 2020a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 2021a23fd118Syl u64 val64; 2022a23fd118Syl u8 spdm_bar_num; 2023a23fd118Syl u32 spdm_bar_offset; 2024a23fd118Syl int spdm_table_size; 2025a23fd118Syl int i; 2026a23fd118Syl 2027a23fd118Syl if (!hldev->config.rth_spdm_en) { 2028a23fd118Syl return XGE_HAL_OK; 2029a23fd118Syl } 2030a23fd118Syl 2031a23fd118Syl /* 2032a23fd118Syl * Retrieve the base address of SPDM Table. 2033a23fd118Syl */ 2034a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, 2035a23fd118Syl hldev->regh0, &bar0->spdm_bir_offset); 2036a23fd118Syl 2037a23fd118Syl spdm_bar_num = XGE_HAL_SPDM_PCI_BAR_NUM(val64); 2038a23fd118Syl spdm_bar_offset = XGE_HAL_SPDM_PCI_BAR_OFFSET(val64); 2039a23fd118Syl 2040a23fd118Syl 2041a23fd118Syl /* 2042a23fd118Syl * spdm_bar_num specifies the PCI bar num register used to 2043a23fd118Syl * address the memory space. spdm_bar_offset specifies the offset 2044a23fd118Syl * of the SPDM memory with in the bar num memory space. 2045a23fd118Syl */ 2046a23fd118Syl switch (spdm_bar_num) { 2047a23fd118Syl case 0: 2048a23fd118Syl { 2049a23fd118Syl hldev->spdm_mem_base = (char *)bar0 + 2050a23fd118Syl (spdm_bar_offset * 8); 2051a23fd118Syl break; 2052a23fd118Syl } 2053a23fd118Syl case 1: 2054a23fd118Syl { 2055a23fd118Syl char *bar1 = (char *)hldev->bar1; 2056a23fd118Syl hldev->spdm_mem_base = bar1 + (spdm_bar_offset * 8); 2057a23fd118Syl break; 2058a23fd118Syl } 2059a23fd118Syl default: 2060a23fd118Syl xge_assert(((spdm_bar_num != 0) && (spdm_bar_num != 1))); 2061a23fd118Syl } 2062a23fd118Syl 2063a23fd118Syl /* 2064a23fd118Syl * Retrieve the size of SPDM table(number of entries). 2065a23fd118Syl */ 2066a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, 2067a23fd118Syl hldev->regh0, &bar0->spdm_structure); 2068a23fd118Syl hldev->spdm_max_entries = XGE_HAL_SPDM_MAX_ENTRIES(val64); 2069a23fd118Syl 2070a23fd118Syl 2071a23fd118Syl spdm_table_size = hldev->spdm_max_entries * 2072a23fd118Syl sizeof(xge_hal_spdm_entry_t); 2073a23fd118Syl if (hldev->spdm_table == NULL) { 2074a23fd118Syl void *mem; 2075a23fd118Syl 2076a23fd118Syl /* 2077a23fd118Syl * Allocate memory to hold the copy of SPDM table. 2078a23fd118Syl */ 2079a23fd118Syl if ((hldev->spdm_table = (xge_hal_spdm_entry_t **) 2080a23fd118Syl xge_os_malloc( 2081a23fd118Syl hldev->pdev, 2082a23fd118Syl (sizeof(xge_hal_spdm_entry_t *) * 2083a23fd118Syl hldev->spdm_max_entries))) == NULL) { 2084a23fd118Syl return XGE_HAL_ERR_OUT_OF_MEMORY; 2085a23fd118Syl } 2086a23fd118Syl 2087a23fd118Syl if ((mem = xge_os_malloc(hldev->pdev, spdm_table_size)) == NULL) 2088a23fd118Syl { 2089a23fd118Syl xge_os_free(hldev->pdev, hldev->spdm_table, 2090a23fd118Syl (sizeof(xge_hal_spdm_entry_t *) * 2091a23fd118Syl hldev->spdm_max_entries)); 2092a23fd118Syl return XGE_HAL_ERR_OUT_OF_MEMORY; 2093a23fd118Syl } 2094a23fd118Syl 2095a23fd118Syl xge_os_memzero(mem, spdm_table_size); 2096a23fd118Syl for (i = 0; i < hldev->spdm_max_entries; i++) { 2097a23fd118Syl hldev->spdm_table[i] = (xge_hal_spdm_entry_t *) 2098a23fd118Syl ((char *)mem + 2099a23fd118Syl i * sizeof(xge_hal_spdm_entry_t)); 2100a23fd118Syl } 2101a23fd118Syl xge_os_spin_lock_init(&hldev->spdm_lock, hldev->pdev); 2102a23fd118Syl } else { 2103a23fd118Syl /* 2104a23fd118Syl * We are here because the host driver tries to 2105a23fd118Syl * do a soft reset on the device. 2106a23fd118Syl * Since the device soft reset clears the SPDM table, copy 2107a23fd118Syl * the entries from the local SPDM table to the actual one. 2108a23fd118Syl */ 2109a23fd118Syl xge_os_spin_lock(&hldev->spdm_lock); 2110a23fd118Syl for (i = 0; i < hldev->spdm_max_entries; i++) { 2111a23fd118Syl xge_hal_spdm_entry_t *spdm_entry = hldev->spdm_table[i]; 2112a23fd118Syl 2113a23fd118Syl if (spdm_entry->in_use) { 2114a23fd118Syl if (__hal_spdm_entry_add(hldev, 2115a23fd118Syl &spdm_entry->src_ip, 2116a23fd118Syl &spdm_entry->dst_ip, 2117a23fd118Syl spdm_entry->l4_sp, 2118a23fd118Syl spdm_entry->l4_dp, 2119a23fd118Syl spdm_entry->is_tcp, 2120a23fd118Syl spdm_entry->is_ipv4, 2121a23fd118Syl spdm_entry->tgt_queue, 2122a23fd118Syl spdm_entry->jhash_value, 2123a23fd118Syl spdm_entry->spdm_entry) 2124a23fd118Syl != XGE_HAL_OK) { 2125a23fd118Syl /* Log an warning */ 21267eced415Sxw xge_debug_device(XGE_ERR, 2127a23fd118Syl "SPDM table update from local" 2128a23fd118Syl " memory failed"); 2129a23fd118Syl } 2130a23fd118Syl } 2131a23fd118Syl } 2132a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 2133a23fd118Syl } 2134a23fd118Syl 2135a23fd118Syl /* 2136a23fd118Syl * Set the receive traffic steering mode from default(classic) 2137a23fd118Syl * to enhanced. 2138a23fd118Syl */ 2139a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, 2140a23fd118Syl hldev->regh0, &bar0->rts_ctrl); 2141a23fd118Syl val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 2142a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2143a23fd118Syl val64, &bar0->rts_ctrl); 2144a23fd118Syl 2145a23fd118Syl /* 2146a23fd118Syl * We may not need to configure rts_rth_jhash_cfg register as the 2147a23fd118Syl * default values are good enough to calculate the hash. 2148a23fd118Syl */ 2149a23fd118Syl 2150a23fd118Syl /* 2151a23fd118Syl * As of now, set all the rth mask registers to zero. TODO. 2152a23fd118Syl */ 2153a23fd118Syl for(i = 0; i < 5; i++) { 2154a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2155a23fd118Syl 0, &bar0->rts_rth_hash_mask[i]); 2156a23fd118Syl } 2157a23fd118Syl 2158a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2159a23fd118Syl 0, &bar0->rts_rth_hash_mask_5); 2160a23fd118Syl 2161a23fd118Syl if (hldev->config.rth_spdm_use_l4) { 2162a23fd118Syl val64 = XGE_HAL_RTH_STATUS_SPDM_USE_L4; 2163a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2164a23fd118Syl val64, &bar0->rts_rth_status); 2165a23fd118Syl } 2166a23fd118Syl 2167a23fd118Syl val64 = XGE_HAL_RTS_RTH_EN; 2168a23fd118Syl val64 |= XGE_HAL_RTS_RTH_IPV4_EN | XGE_HAL_RTS_RTH_TCP_IPV4_EN; 2169a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2170a23fd118Syl &bar0->rts_rth_cfg); 2171a23fd118Syl 2172a23fd118Syl 2173a23fd118Syl return XGE_HAL_OK; 2174a23fd118Syl } 2175a23fd118Syl 2176a23fd118Syl /* 2177a23fd118Syl * __hal_device_pci_init 2178a23fd118Syl * @hldev: HAL device handle. 2179a23fd118Syl * 2180a23fd118Syl * Initialize certain PCI/PCI-X configuration registers 2181a23fd118Syl * with recommended values. Save config space for future hw resets. 2182a23fd118Syl */ 2183a23fd118Syl static void 2184a23fd118Syl __hal_device_pci_init(xge_hal_device_t *hldev) 2185a23fd118Syl { 2186a23fd118Syl int i, pcisize = 0; 2187a23fd118Syl u16 cmd = 0; 2188a23fd118Syl u8 val; 2189a23fd118Syl 21907eced415Sxw /* Store PCI device ID and revision for future references where in we 21917eced415Sxw * decide Xena revision using PCI sub system ID */ 21927eced415Sxw xge_os_pci_read16(hldev->pdev,hldev->cfgh, 21937eced415Sxw xge_offsetof(xge_hal_pci_config_le_t, device_id), 21947eced415Sxw &hldev->device_id); 21957eced415Sxw xge_os_pci_read8(hldev->pdev,hldev->cfgh, 21967eced415Sxw xge_offsetof(xge_hal_pci_config_le_t, revision), 21977eced415Sxw &hldev->revision); 21987eced415Sxw 21997eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 22007eced415Sxw pcisize = XGE_HAL_PCISIZE_HERC; 22017eced415Sxw else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 22027eced415Sxw pcisize = XGE_HAL_PCISIZE_XENA; 22037eced415Sxw 22047eced415Sxw /* save original PCI config space to restore it on device_terminate() */ 22057eced415Sxw for (i = 0; i < pcisize; i++) { 22067eced415Sxw xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, 22077eced415Sxw (u32*)&hldev->pci_config_space_bios + i); 22087eced415Sxw } 22097eced415Sxw 2210a23fd118Syl /* Set the PErr Repconse bit and SERR in PCI command register. */ 2211a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2212a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, command), &cmd); 2213a23fd118Syl cmd |= 0x140; 2214a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2215a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, command), cmd); 2216a23fd118Syl 2217a23fd118Syl /* Set user spcecified value for the PCI Latency Timer */ 2218a23fd118Syl if (hldev->config.latency_timer && 2219a23fd118Syl hldev->config.latency_timer != XGE_HAL_USE_BIOS_DEFAULT_LATENCY) { 2220a23fd118Syl xge_os_pci_write8(hldev->pdev, hldev->cfgh, 2221a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, 2222a23fd118Syl latency_timer), 2223a23fd118Syl (u8)hldev->config.latency_timer); 2224a23fd118Syl } 2225a23fd118Syl /* Read back latency timer to reflect it into user level */ 2226a23fd118Syl xge_os_pci_read8(hldev->pdev, hldev->cfgh, 2227a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, latency_timer), &val); 2228a23fd118Syl hldev->config.latency_timer = val; 2229a23fd118Syl 2230a23fd118Syl /* Enable Data Parity Error Recovery in PCI-X command register. */ 2231a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2232a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); 2233a23fd118Syl cmd |= 1; 2234a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2235a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd); 2236a23fd118Syl 2237a23fd118Syl /* Set MMRB count in PCI-X command register. */ 2238a23fd118Syl if (hldev->config.mmrb_count != XGE_HAL_DEFAULT_BIOS_MMRB_COUNT) { 2239a23fd118Syl cmd &= 0xFFF3; 2240a23fd118Syl cmd |= hldev->config.mmrb_count << 2; 2241a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2242a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2243a23fd118Syl cmd); 2244a23fd118Syl } 2245a23fd118Syl /* Read back MMRB count to reflect it into user level */ 2246a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2247a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2248a23fd118Syl &cmd); 2249a23fd118Syl cmd &= 0x000C; 2250a23fd118Syl hldev->config.mmrb_count = cmd>>2; 2251a23fd118Syl 2252a23fd118Syl /* Setting Maximum outstanding splits based on system type. */ 2253a23fd118Syl if (hldev->config.max_splits_trans != XGE_HAL_USE_BIOS_DEFAULT_SPLITS) { 2254a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2255a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2256a23fd118Syl &cmd); 2257a23fd118Syl cmd &= 0xFF8F; 2258a23fd118Syl cmd |= hldev->config.max_splits_trans << 4; 2259a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2260a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), 2261a23fd118Syl cmd); 2262a23fd118Syl } 2263a23fd118Syl 2264a23fd118Syl /* Read back max split trans to reflect it into user level */ 2265a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2266a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); 2267a23fd118Syl cmd &= 0x0070; 2268a23fd118Syl hldev->config.max_splits_trans = cmd>>4; 2269a23fd118Syl 2270a23fd118Syl /* Forcibly disabling relaxed ordering capability of the card. */ 2271a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 2272a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd); 2273a23fd118Syl cmd &= 0xFFFD; 2274a23fd118Syl xge_os_pci_write16(hldev->pdev, hldev->cfgh, 2275a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd); 2276a23fd118Syl 2277a23fd118Syl /* save PCI config space for future resets */ 2278a23fd118Syl for (i = 0; i < pcisize; i++) { 2279a23fd118Syl xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, 2280a23fd118Syl (u32*)&hldev->pci_config_space + i); 2281a23fd118Syl } 2282a23fd118Syl } 2283a23fd118Syl 2284a23fd118Syl /* 2285a23fd118Syl * __hal_device_pci_info_get - Get PCI bus informations such as width, frequency 2286a23fd118Syl * and mode. 2287a23fd118Syl * @devh: HAL device handle. 2288a23fd118Syl * @pci_mode: pointer to a variable of enumerated type 2289a23fd118Syl * xge_hal_pci_mode_e{}. 2290a23fd118Syl * @bus_frequency: pointer to a variable of enumerated type 2291a23fd118Syl * xge_hal_pci_bus_frequency_e{}. 2292a23fd118Syl * @bus_width: pointer to a variable of enumerated type 2293a23fd118Syl * xge_hal_pci_bus_width_e{}. 2294a23fd118Syl * 2295a23fd118Syl * Get pci mode, frequency, and PCI bus width. 2296a23fd118Syl * 2297a23fd118Syl * Returns: one of the xge_hal_status_e{} enumerated types. 2298a23fd118Syl * XGE_HAL_OK - for success. 2299a23fd118Syl * XGE_HAL_ERR_INVALID_PCI_INFO - for invalid PCI information from the card. 2300a23fd118Syl * XGE_HAL_ERR_BAD_DEVICE_ID - for invalid card. 2301a23fd118Syl * 2302a23fd118Syl * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e. 2303a23fd118Syl */ 2304a23fd118Syl static xge_hal_status_e 2305a23fd118Syl __hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, 2306a23fd118Syl xge_hal_pci_bus_frequency_e *bus_frequency, 2307a23fd118Syl xge_hal_pci_bus_width_e *bus_width) 2308a23fd118Syl { 2309a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 2310a23fd118Syl xge_hal_status_e rc_status = XGE_HAL_OK; 2311a23fd118Syl xge_hal_card_e card_id = xge_hal_device_check_id (devh); 2312a23fd118Syl 2313a23fd118Syl #ifdef XGE_HAL_HERC_EMULATION 2314a23fd118Syl hldev->config.pci_freq_mherz = 2315a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2316a23fd118Syl *bus_frequency = 2317a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2318a23fd118Syl *pci_mode = XGE_HAL_PCI_66MHZ_MODE; 2319a23fd118Syl #else 2320a23fd118Syl if (card_id == XGE_HAL_CARD_HERC) { 2321a23fd118Syl xge_hal_pci_bar0_t *bar0 = 2322a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2323a23fd118Syl u64 pci_info = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2324a23fd118Syl &bar0->pci_info); 2325a23fd118Syl if (XGE_HAL_PCI_32_BIT & pci_info) 2326a23fd118Syl *bus_width = XGE_HAL_PCI_BUS_WIDTH_32BIT; 2327a23fd118Syl else 2328a23fd118Syl *bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT; 2329a23fd118Syl switch((pci_info & XGE_HAL_PCI_INFO)>>60) 2330a23fd118Syl { 2331a23fd118Syl case XGE_HAL_PCI_33MHZ_MODE: 2332a23fd118Syl *bus_frequency = 2333a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_33MHZ; 2334a23fd118Syl *pci_mode = XGE_HAL_PCI_33MHZ_MODE; 2335a23fd118Syl break; 2336a23fd118Syl case XGE_HAL_PCI_66MHZ_MODE: 2337a23fd118Syl *bus_frequency = 2338a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2339a23fd118Syl *pci_mode = XGE_HAL_PCI_66MHZ_MODE; 2340a23fd118Syl break; 2341a23fd118Syl case XGE_HAL_PCIX_M1_66MHZ_MODE: 2342a23fd118Syl *bus_frequency = 2343a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_66MHZ; 2344a23fd118Syl *pci_mode = XGE_HAL_PCIX_M1_66MHZ_MODE; 2345a23fd118Syl break; 2346a23fd118Syl case XGE_HAL_PCIX_M1_100MHZ_MODE: 2347a23fd118Syl *bus_frequency = 2348a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_100MHZ; 2349a23fd118Syl *pci_mode = XGE_HAL_PCIX_M1_100MHZ_MODE; 2350a23fd118Syl break; 2351a23fd118Syl case XGE_HAL_PCIX_M1_133MHZ_MODE: 2352a23fd118Syl *bus_frequency = 2353a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; 2354a23fd118Syl *pci_mode = XGE_HAL_PCIX_M1_133MHZ_MODE; 2355a23fd118Syl break; 2356a23fd118Syl case XGE_HAL_PCIX_M2_66MHZ_MODE: 2357a23fd118Syl *bus_frequency = 2358a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; 2359a23fd118Syl *pci_mode = XGE_HAL_PCIX_M2_66MHZ_MODE; 2360a23fd118Syl break; 2361a23fd118Syl case XGE_HAL_PCIX_M2_100MHZ_MODE: 2362a23fd118Syl *bus_frequency = 2363a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_200MHZ; 2364a23fd118Syl *pci_mode = XGE_HAL_PCIX_M2_100MHZ_MODE; 2365a23fd118Syl break; 2366a23fd118Syl case XGE_HAL_PCIX_M2_133MHZ_MODE: 2367a23fd118Syl *bus_frequency = 2368a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_266MHZ; 2369a23fd118Syl *pci_mode = XGE_HAL_PCIX_M2_133MHZ_MODE; 2370a23fd118Syl break; 2371a23fd118Syl case XGE_HAL_PCIX_M1_RESERVED: 2372a23fd118Syl case XGE_HAL_PCIX_M1_66MHZ_NS: 2373a23fd118Syl case XGE_HAL_PCIX_M1_100MHZ_NS: 2374a23fd118Syl case XGE_HAL_PCIX_M1_133MHZ_NS: 2375a23fd118Syl case XGE_HAL_PCIX_M2_RESERVED: 2376a23fd118Syl case XGE_HAL_PCIX_533_RESERVED: 2377a23fd118Syl default: 2378a23fd118Syl rc_status = XGE_HAL_ERR_INVALID_PCI_INFO; 2379a23fd118Syl xge_debug_device(XGE_ERR, 23808347601bSyl "invalid pci info "XGE_OS_LLXFMT, 2381a23fd118Syl (unsigned long long)pci_info); 2382a23fd118Syl break; 2383a23fd118Syl } 2384a23fd118Syl if (rc_status != XGE_HAL_ERR_INVALID_PCI_INFO) 2385a23fd118Syl xge_debug_device(XGE_TRACE, "PCI info: mode %d width " 2386a23fd118Syl "%d frequency %d", *pci_mode, *bus_width, 2387a23fd118Syl *bus_frequency); 23888347601bSyl if (hldev->config.pci_freq_mherz == 23898347601bSyl XGE_HAL_DEFAULT_USE_HARDCODE) { 23908347601bSyl hldev->config.pci_freq_mherz = *bus_frequency; 23918347601bSyl } 2392a23fd118Syl } 2393a23fd118Syl /* for XENA, we report PCI mode, only. PCI bus frequency, and bus width 2394a23fd118Syl * are set to unknown */ 2395a23fd118Syl else if (card_id == XGE_HAL_CARD_XENA) { 2396a23fd118Syl u32 pcix_status; 2397a23fd118Syl u8 dev_num, bus_num; 2398a23fd118Syl /* initialize defaults for XENA */ 2399a23fd118Syl *bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN; 2400a23fd118Syl *bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN; 2401a23fd118Syl xge_os_pci_read32(hldev->pdev, hldev->cfgh, 2402a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, pcix_status), 2403a23fd118Syl &pcix_status); 2404a23fd118Syl dev_num = (u8)((pcix_status & 0xF8) >> 3); 2405a23fd118Syl bus_num = (u8)((pcix_status & 0xFF00) >> 8); 2406a23fd118Syl if (dev_num == 0 && bus_num == 0) 2407a23fd118Syl *pci_mode = XGE_HAL_PCI_BASIC_MODE; 2408a23fd118Syl else 2409a23fd118Syl *pci_mode = XGE_HAL_PCIX_BASIC_MODE; 2410a23fd118Syl xge_debug_device(XGE_TRACE, "PCI info: mode %d", *pci_mode); 2411a23fd118Syl if (hldev->config.pci_freq_mherz == 2412a23fd118Syl XGE_HAL_DEFAULT_USE_HARDCODE) { 2413a23fd118Syl /* 2414a23fd118Syl * There is no way to detect BUS frequency on Xena, 2415a23fd118Syl * so, in case of automatic configuration we hopelessly 2416a23fd118Syl * assume 133MHZ. 2417a23fd118Syl */ 2418a23fd118Syl hldev->config.pci_freq_mherz = 2419a23fd118Syl XGE_HAL_PCI_BUS_FREQUENCY_133MHZ; 2420a23fd118Syl } 24217eced415Sxw } else if (card_id == XGE_HAL_CARD_TITAN) { 24227eced415Sxw *bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT; 24237eced415Sxw *bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_250MHZ; 24247eced415Sxw if (hldev->config.pci_freq_mherz == 24257eced415Sxw XGE_HAL_DEFAULT_USE_HARDCODE) { 24267eced415Sxw hldev->config.pci_freq_mherz = *bus_frequency; 24277eced415Sxw } 2428a23fd118Syl } else{ 2429a23fd118Syl rc_status = XGE_HAL_ERR_BAD_DEVICE_ID; 2430a23fd118Syl xge_debug_device(XGE_ERR, "invalid device id %d", card_id); 2431a23fd118Syl } 2432a23fd118Syl #endif 2433a23fd118Syl 2434a23fd118Syl return rc_status; 2435a23fd118Syl } 2436a23fd118Syl 2437a23fd118Syl /* 2438a23fd118Syl * __hal_device_handle_link_up_ind 2439a23fd118Syl * @hldev: HAL device handle. 2440a23fd118Syl * 2441a23fd118Syl * Link up indication handler. The function is invoked by HAL when 2442a23fd118Syl * Xframe indicates that the link is up for programmable amount of time. 2443a23fd118Syl */ 2444a23fd118Syl static int 2445a23fd118Syl __hal_device_handle_link_up_ind(xge_hal_device_t *hldev) 2446a23fd118Syl { 2447a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2448a23fd118Syl u64 val64; 2449a23fd118Syl 2450a23fd118Syl /* 2451a23fd118Syl * If the previous link state is not down, return. 2452a23fd118Syl */ 2453a23fd118Syl if (hldev->link_state == XGE_HAL_LINK_UP) { 2454a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2455a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){ 2456a23fd118Syl val64 = xge_os_pio_mem_read64( 2457a23fd118Syl hldev->pdev, hldev->regh0, 2458a23fd118Syl &bar0->misc_int_mask); 2459a23fd118Syl val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2460a23fd118Syl val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2461a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2462a23fd118Syl val64, &bar0->misc_int_mask); 2463a23fd118Syl } 2464a23fd118Syl #endif 2465a23fd118Syl xge_debug_device(XGE_TRACE, 2466a23fd118Syl "link up indication while link is up, ignoring.."); 2467a23fd118Syl return 0; 2468a23fd118Syl } 2469a23fd118Syl 2470a23fd118Syl /* Now re-enable it as due to noise, hardware turned it off */ 2471a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2472a23fd118Syl &bar0->adapter_control); 2473a23fd118Syl val64 |= XGE_HAL_ADAPTER_CNTL_EN; 2474a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */ 2475a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2476a23fd118Syl &bar0->adapter_control); 2477a23fd118Syl 2478a23fd118Syl /* Turn on the Laser */ 2479a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2480a23fd118Syl &bar0->adapter_control); 2481a23fd118Syl val64 = val64|(XGE_HAL_ADAPTER_EOI_TX_ON | 2482a23fd118Syl XGE_HAL_ADAPTER_LED_ON); 2483a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2484a23fd118Syl &bar0->adapter_control); 2485a23fd118Syl 2486a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2487a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2488a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2489a23fd118Syl &bar0->adapter_status); 2490a23fd118Syl if (val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2491a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) { 2492a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 2493a23fd118Syl "fail to transition link to up..."); 2494a23fd118Syl return 0; 2495a23fd118Syl } 2496a23fd118Syl else { 2497a23fd118Syl /* 2498a23fd118Syl * Mask the Link Up interrupt and unmask the Link Down 2499a23fd118Syl * interrupt. 2500a23fd118Syl */ 2501a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2502a23fd118Syl &bar0->misc_int_mask); 2503a23fd118Syl val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2504a23fd118Syl val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2505a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2506a23fd118Syl &bar0->misc_int_mask); 2507a23fd118Syl xge_debug_device(XGE_TRACE, "calling link up.."); 2508a23fd118Syl hldev->link_state = XGE_HAL_LINK_UP; 2509a23fd118Syl 2510a23fd118Syl /* notify ULD */ 2511a23fd118Syl if (g_xge_hal_driver->uld_callbacks.link_up) { 2512a23fd118Syl g_xge_hal_driver->uld_callbacks.link_up( 2513a23fd118Syl hldev->upper_layer_info); 2514a23fd118Syl } 2515a23fd118Syl return 1; 2516a23fd118Syl } 2517a23fd118Syl } 2518a23fd118Syl #endif 2519a23fd118Syl xge_os_mdelay(1); 2520a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0, 2521a23fd118Syl (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2522a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT), 2523a23fd118Syl XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) { 2524a23fd118Syl 2525a23fd118Syl /* notify ULD */ 2526a23fd118Syl (void) xge_queue_produce_context(hldev->queueh, 25277eced415Sxw XGE_HAL_EVENT_LINK_IS_UP, hldev); 2528a23fd118Syl /* link is up after been enabled */ 2529a23fd118Syl return 1; 2530a23fd118Syl } else { 2531a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 2532a23fd118Syl "fail to transition link to up..."); 2533a23fd118Syl return 0; 2534a23fd118Syl } 2535a23fd118Syl } 2536a23fd118Syl 2537a23fd118Syl /* 2538a23fd118Syl * __hal_device_handle_link_down_ind 2539a23fd118Syl * @hldev: HAL device handle. 2540a23fd118Syl * 2541a23fd118Syl * Link down indication handler. The function is invoked by HAL when 2542a23fd118Syl * Xframe indicates that the link is down. 2543a23fd118Syl */ 2544a23fd118Syl static int 2545a23fd118Syl __hal_device_handle_link_down_ind(xge_hal_device_t *hldev) 2546a23fd118Syl { 2547a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2548a23fd118Syl u64 val64; 2549a23fd118Syl 2550a23fd118Syl /* 2551a23fd118Syl * If the previous link state is not up, return. 2552a23fd118Syl */ 2553a23fd118Syl if (hldev->link_state == XGE_HAL_LINK_DOWN) { 2554a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2555a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){ 2556a23fd118Syl val64 = xge_os_pio_mem_read64( 2557a23fd118Syl hldev->pdev, hldev->regh0, 2558a23fd118Syl &bar0->misc_int_mask); 2559a23fd118Syl val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2560a23fd118Syl val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2561a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2562a23fd118Syl val64, &bar0->misc_int_mask); 2563a23fd118Syl } 2564a23fd118Syl #endif 2565a23fd118Syl xge_debug_device(XGE_TRACE, 2566a23fd118Syl "link down indication while link is down, ignoring.."); 2567a23fd118Syl return 0; 2568a23fd118Syl } 2569a23fd118Syl xge_os_mdelay(1); 2570a23fd118Syl 2571a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2572a23fd118Syl &bar0->adapter_control); 2573a23fd118Syl 2574a23fd118Syl /* try to debounce the link only if the adapter is enabled. */ 2575a23fd118Syl if (val64 & XGE_HAL_ADAPTER_CNTL_EN) { 2576a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0, 2577a23fd118Syl (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 2578a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT), 2579a23fd118Syl XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) { 2580a23fd118Syl xge_debug_device(XGE_TRACE, 2581a23fd118Syl "link is actually up (possible noisy link?), ignoring."); 2582a23fd118Syl return(0); 2583a23fd118Syl } 2584a23fd118Syl } 2585a23fd118Syl 2586a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2587a23fd118Syl &bar0->adapter_control); 2588a23fd118Syl /* turn off LED */ 2589a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); 2590a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2591a23fd118Syl &bar0->adapter_control); 2592a23fd118Syl 2593a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 2594a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 2595a23fd118Syl /* 2596a23fd118Syl * Mask the Link Down interrupt and unmask the Link up 2597a23fd118Syl * interrupt 2598a23fd118Syl */ 2599a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2600a23fd118Syl &bar0->misc_int_mask); 2601a23fd118Syl val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT; 2602a23fd118Syl val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT; 2603a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2604a23fd118Syl &bar0->misc_int_mask); 2605a23fd118Syl 2606a23fd118Syl /* link is down */ 2607a23fd118Syl xge_debug_device(XGE_TRACE, "calling link down.."); 2608a23fd118Syl hldev->link_state = XGE_HAL_LINK_DOWN; 2609a23fd118Syl 2610a23fd118Syl /* notify ULD */ 2611a23fd118Syl if (g_xge_hal_driver->uld_callbacks.link_down) { 2612a23fd118Syl g_xge_hal_driver->uld_callbacks.link_down( 2613a23fd118Syl hldev->upper_layer_info); 2614a23fd118Syl } 2615a23fd118Syl return 1; 2616a23fd118Syl } 2617a23fd118Syl #endif 2618a23fd118Syl /* notify ULD */ 2619a23fd118Syl (void) xge_queue_produce_context(hldev->queueh, 26207eced415Sxw XGE_HAL_EVENT_LINK_IS_DOWN, hldev); 2621a23fd118Syl /* link is down */ 2622a23fd118Syl return 1; 2623a23fd118Syl } 2624a23fd118Syl /* 2625a23fd118Syl * __hal_device_handle_link_state_change 2626a23fd118Syl * @hldev: HAL device handle. 2627a23fd118Syl * 2628a23fd118Syl * Link state change handler. The function is invoked by HAL when 2629a23fd118Syl * Xframe indicates link state change condition. The code here makes sure to 2630a23fd118Syl * 1) ignore redundant state change indications; 2631a23fd118Syl * 2) execute link-up sequence, and handle the failure to bring the link up; 2632a23fd118Syl * 3) generate XGE_HAL_LINK_UP/DOWN event for the subsequent handling by 2633a23fd118Syl * upper-layer driver (ULD). 2634a23fd118Syl */ 2635a23fd118Syl static int 2636a23fd118Syl __hal_device_handle_link_state_change(xge_hal_device_t *hldev) 2637a23fd118Syl { 2638a23fd118Syl u64 hw_status; 2639a23fd118Syl int hw_link_state; 2640a23fd118Syl int retcode; 2641a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2642a23fd118Syl u64 val64; 26438347601bSyl int i = 0; 2644a23fd118Syl 2645a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2646a23fd118Syl &bar0->adapter_control); 2647a23fd118Syl 2648a23fd118Syl /* If the adapter is not enabled but the hal thinks we are in the up 2649a23fd118Syl * state then transition to the down state. 2650a23fd118Syl */ 2651a23fd118Syl if ( !(val64 & XGE_HAL_ADAPTER_CNTL_EN) && 2652a23fd118Syl (hldev->link_state == XGE_HAL_LINK_UP) ) { 2653a23fd118Syl return(__hal_device_handle_link_down_ind(hldev)); 2654a23fd118Syl } 2655a23fd118Syl 26568347601bSyl do { 26578347601bSyl xge_os_mdelay(1); 26588347601bSyl (void) xge_hal_device_status(hldev, &hw_status); 26598347601bSyl hw_link_state = (hw_status & 26608347601bSyl (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 26618347601bSyl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) ? 26628347601bSyl XGE_HAL_LINK_DOWN : XGE_HAL_LINK_UP; 26638347601bSyl 26648347601bSyl /* check if the current link state is still considered 26658347601bSyl * to be changed. This way we will make sure that this is 26668347601bSyl * not a noise which needs to be filtered out */ 26678347601bSyl if (hldev->link_state == hw_link_state) 26688347601bSyl break; 26698347601bSyl } while (i++ < hldev->config.link_valid_cnt); 2670a23fd118Syl 2671a23fd118Syl /* If the current link state is same as previous, just return */ 2672a23fd118Syl if (hldev->link_state == hw_link_state) 2673a23fd118Syl retcode = 0; 2674a23fd118Syl /* detected state change */ 2675a23fd118Syl else if (hw_link_state == XGE_HAL_LINK_UP) 2676a23fd118Syl retcode = __hal_device_handle_link_up_ind(hldev); 2677a23fd118Syl else 2678a23fd118Syl retcode = __hal_device_handle_link_down_ind(hldev); 2679a23fd118Syl return retcode; 2680a23fd118Syl } 2681a23fd118Syl 2682a23fd118Syl /* 2683a23fd118Syl * 2684a23fd118Syl */ 2685a23fd118Syl static void 2686a23fd118Syl __hal_device_handle_serr(xge_hal_device_t *hldev, char *reg, u64 value) 2687a23fd118Syl { 2688a23fd118Syl hldev->stats.sw_dev_err_stats.serr_cnt++; 2689a23fd118Syl if (hldev->config.dump_on_serr) { 2690a23fd118Syl #ifdef XGE_HAL_USE_MGMT_AUX 2691a23fd118Syl (void) xge_hal_aux_device_dump(hldev); 2692a23fd118Syl #endif 2693a23fd118Syl } 2694a23fd118Syl 2695a23fd118Syl (void) xge_queue_produce(hldev->queueh, XGE_HAL_EVENT_SERR, hldev, 2696a23fd118Syl 1, sizeof(u64), (void *)&value); 2697a23fd118Syl 26988347601bSyl xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, 2699a23fd118Syl (unsigned long long) value); 2700a23fd118Syl } 2701a23fd118Syl 2702a23fd118Syl /* 2703a23fd118Syl * 2704a23fd118Syl */ 2705a23fd118Syl static void 2706a23fd118Syl __hal_device_handle_eccerr(xge_hal_device_t *hldev, char *reg, u64 value) 2707a23fd118Syl { 2708a23fd118Syl if (hldev->config.dump_on_eccerr) { 2709a23fd118Syl #ifdef XGE_HAL_USE_MGMT_AUX 2710a23fd118Syl (void) xge_hal_aux_device_dump(hldev); 2711a23fd118Syl #endif 2712a23fd118Syl } 2713a23fd118Syl 2714a23fd118Syl /* Herc smart enough to recover on its own! */ 2715a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 2716a23fd118Syl (void) xge_queue_produce(hldev->queueh, 2717a23fd118Syl XGE_HAL_EVENT_ECCERR, hldev, 2718a23fd118Syl 1, sizeof(u64), (void *)&value); 2719a23fd118Syl } 2720a23fd118Syl 27218347601bSyl xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, 2722a23fd118Syl (unsigned long long) value); 2723a23fd118Syl } 2724a23fd118Syl 2725a23fd118Syl /* 2726a23fd118Syl * 2727a23fd118Syl */ 2728a23fd118Syl static void 2729a23fd118Syl __hal_device_handle_parityerr(xge_hal_device_t *hldev, char *reg, u64 value) 2730a23fd118Syl { 2731a23fd118Syl if (hldev->config.dump_on_parityerr) { 2732a23fd118Syl #ifdef XGE_HAL_USE_MGMT_AUX 2733a23fd118Syl (void) xge_hal_aux_device_dump(hldev); 2734a23fd118Syl #endif 2735a23fd118Syl } 2736a23fd118Syl (void) xge_queue_produce_context(hldev->queueh, 2737a23fd118Syl XGE_HAL_EVENT_PARITYERR, hldev); 2738a23fd118Syl 27398347601bSyl xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg, 2740a23fd118Syl (unsigned long long) value); 2741a23fd118Syl } 2742a23fd118Syl 2743a23fd118Syl /* 2744a23fd118Syl * 2745a23fd118Syl */ 2746a23fd118Syl static void 2747a23fd118Syl __hal_device_handle_targetabort(xge_hal_device_t *hldev) 2748a23fd118Syl { 2749a23fd118Syl (void) xge_queue_produce_context(hldev->queueh, 2750a23fd118Syl XGE_HAL_EVENT_TARGETABORT, hldev); 2751a23fd118Syl } 2752a23fd118Syl 2753a23fd118Syl 2754a23fd118Syl /* 2755a23fd118Syl * __hal_device_hw_initialize 2756a23fd118Syl * @hldev: HAL device handle. 2757a23fd118Syl * 2758a23fd118Syl * Initialize Xframe hardware. 2759a23fd118Syl */ 2760a23fd118Syl static xge_hal_status_e 2761a23fd118Syl __hal_device_hw_initialize(xge_hal_device_t *hldev) 2762a23fd118Syl { 2763a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 2764a23fd118Syl xge_hal_status_e status; 2765a23fd118Syl u64 val64; 2766a23fd118Syl 2767a23fd118Syl /* Set proper endian settings and verify the same by reading the PIF 2768a23fd118Syl * Feed-back register. */ 2769a23fd118Syl status = __hal_device_set_swapper(hldev); 2770a23fd118Syl if (status != XGE_HAL_OK) { 2771a23fd118Syl return status; 2772a23fd118Syl } 2773a23fd118Syl 2774a23fd118Syl /* update the pci mode, frequency, and width */ 2775a23fd118Syl if (__hal_device_pci_info_get(hldev, &hldev->pci_mode, 2776a23fd118Syl &hldev->bus_frequency, &hldev->bus_width) != XGE_HAL_OK){ 2777a23fd118Syl hldev->pci_mode = XGE_HAL_PCI_INVALID_MODE; 2778a23fd118Syl hldev->bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN; 2779a23fd118Syl hldev->bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN; 2780a23fd118Syl /* 2781a23fd118Syl * FIXME: this cannot happen. 2782a23fd118Syl * But if it happens we cannot continue just like that 2783a23fd118Syl */ 2784a23fd118Syl xge_debug_device(XGE_ERR, "unable to get pci info"); 2785a23fd118Syl } 2786a23fd118Syl 2787a23fd118Syl if ((hldev->pci_mode == XGE_HAL_PCI_33MHZ_MODE) || 2788a23fd118Syl (hldev->pci_mode == XGE_HAL_PCI_66MHZ_MODE) || 2789a23fd118Syl (hldev->pci_mode == XGE_HAL_PCI_BASIC_MODE)) { 2790a23fd118Syl /* PCI optimization: set TxReqTimeOut 2791a23fd118Syl * register (0x800+0x120) to 0x1ff or 2792a23fd118Syl * something close to this. 2793a23fd118Syl * Note: not to be used for PCI-X! */ 2794a23fd118Syl 2795a23fd118Syl val64 = XGE_HAL_TXREQTO_VAL(0x1FF); 2796a23fd118Syl val64 |= XGE_HAL_TXREQTO_EN; 2797a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 2798a23fd118Syl &bar0->txreqtimeout); 2799a23fd118Syl 2800a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, 2801a23fd118Syl &bar0->read_retry_delay); 2802a23fd118Syl 2803a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL, 2804a23fd118Syl &bar0->write_retry_delay); 2805a23fd118Syl 2806a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI mode"); 2807a23fd118Syl } 2808a23fd118Syl 28097eced415Sxw if (hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_266MHZ || 28107eced415Sxw hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_250MHZ) { 28117eced415Sxw 28127eced415Sxw /* Optimizing for PCI-X 266/250 */ 28137eced415Sxw 28147eced415Sxw val64 = XGE_HAL_TXREQTO_VAL(0x7F); 28157eced415Sxw val64 |= XGE_HAL_TXREQTO_EN; 28167eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 28177eced415Sxw &bar0->txreqtimeout); 28187eced415Sxw 28197eced415Sxw xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI-X 266/250 modes"); 28207eced415Sxw } 28217eced415Sxw 28227eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 28237eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL, 28247eced415Sxw &bar0->read_retry_delay); 28257eced415Sxw 28267eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL, 28277eced415Sxw &bar0->write_retry_delay); 28287eced415Sxw } 28297eced415Sxw 28308347601bSyl /* added this to set the no of bytes used to update lso_bytes_sent 28318347601bSyl returned TxD0 */ 28328347601bSyl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 28338347601bSyl &bar0->pic_control_2); 28347eced415Sxw val64 &= ~XGE_HAL_TXD_WRITE_BC(0x2); 28358347601bSyl val64 |= XGE_HAL_TXD_WRITE_BC(0x4); 28368347601bSyl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 28378347601bSyl &bar0->pic_control_2); 2838a23fd118Syl /* added this to clear the EOI_RESET field while leaving XGXS_RESET 2839a23fd118Syl * in reset, then a 1-second delay */ 2840a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 2841a23fd118Syl XGE_HAL_SW_RESET_XGXS, &bar0->sw_reset); 2842a23fd118Syl xge_os_mdelay(1000); 2843a23fd118Syl 2844a23fd118Syl /* Clear the XGXS_RESET field of the SW_RESET register in order to 2845a23fd118Syl * release the XGXS from reset. Its reset value is 0xA5; write 0x00 2846a23fd118Syl * to activate the XGXS. The core requires a minimum 500 us reset.*/ 2847a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0, &bar0->sw_reset); 2848a23fd118Syl (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2849a23fd118Syl &bar0->sw_reset); 2850a23fd118Syl xge_os_mdelay(1); 2851a23fd118Syl 2852a23fd118Syl /* read registers in all blocks */ 2853a23fd118Syl (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2854a23fd118Syl &bar0->mac_int_mask); 2855a23fd118Syl (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2856a23fd118Syl &bar0->mc_int_mask); 2857a23fd118Syl (void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 2858a23fd118Syl &bar0->xgxs_int_mask); 2859a23fd118Syl 2860a23fd118Syl /* set default MTU and steer based on length*/ 2861a23fd118Syl __hal_ring_mtu_set(hldev, hldev->config.mtu+22); // Alway set 22 bytes extra for steering to work 2862a23fd118Syl 2863a23fd118Syl if (hldev->config.mac.rmac_bcast_en) { 2864a23fd118Syl xge_hal_device_bcast_enable(hldev); 2865a23fd118Syl } else { 2866a23fd118Syl xge_hal_device_bcast_disable(hldev); 2867a23fd118Syl } 2868a23fd118Syl 2869a23fd118Syl #ifndef XGE_HAL_HERC_EMULATION 2870a23fd118Syl __hal_device_xaui_configure(hldev); 2871a23fd118Syl #endif 2872a23fd118Syl __hal_device_mac_link_util_set(hldev); 2873a23fd118Syl 2874a23fd118Syl __hal_device_mac_link_util_set(hldev); 2875a23fd118Syl 2876a23fd118Syl /* 2877a23fd118Syl * Keep its PCI REQ# line asserted during a write 2878a23fd118Syl * transaction up to the end of the transaction 2879a23fd118Syl */ 2880a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 28817eced415Sxw &bar0->misc_control); 28827eced415Sxw 2883a23fd118Syl val64 |= XGE_HAL_MISC_CONTROL_EXT_REQ_EN; 28847eced415Sxw 2885a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 28867eced415Sxw val64, &bar0->misc_control); 28877eced415Sxw 28887eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 28897eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 28907eced415Sxw &bar0->misc_control); 28917eced415Sxw 28927eced415Sxw val64 |= XGE_HAL_MISC_CONTROL_LINK_FAULT; 28937eced415Sxw 28947eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 28957eced415Sxw val64, &bar0->misc_control); 28967eced415Sxw } 2897a23fd118Syl 2898a23fd118Syl /* 28998347601bSyl * bimodal interrupts is when all Rx traffic interrupts 29008347601bSyl * will go to TTI, so we need to adjust RTI settings and 29018347601bSyl * use adaptive TTI timer. We need to make sure RTI is 29028347601bSyl * properly configured to sane value which will not 29038347601bSyl * distrupt bimodal behavior. 2904a23fd118Syl */ 29058347601bSyl if (hldev->config.bimodal_interrupts) { 29068347601bSyl int i; 29078347601bSyl 29088347601bSyl /* force polling_cnt to be "0", otherwise 29098347601bSyl * IRQ workload statistics will be screwed. This could 29108347601bSyl * be worked out in TXPIC handler later. */ 29118347601bSyl hldev->config.isr_polling_cnt = 0; 29128347601bSyl hldev->config.sched_timer_us = 10000; 29138347601bSyl 29148347601bSyl /* disable all TTI < 56 */ 29158347601bSyl for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) { 29168347601bSyl int j; 29178347601bSyl if (!hldev->config.fifo.queue[i].configured) 29188347601bSyl continue; 29198347601bSyl for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) { 29208347601bSyl if (hldev->config.fifo.queue[i].tti[j].enabled) 29218347601bSyl hldev->config.fifo.queue[i].tti[j].enabled = 0; 29228347601bSyl } 2923a23fd118Syl } 29248347601bSyl 29258347601bSyl /* now configure bimodal interrupts */ 29268347601bSyl __hal_device_bimodal_configure(hldev); 2927a23fd118Syl } 2928a23fd118Syl 29298347601bSyl status = __hal_device_tti_configure(hldev, 0); 29308347601bSyl if (status != XGE_HAL_OK) 29318347601bSyl return status; 29328347601bSyl 2933a23fd118Syl status = __hal_device_rti_configure(hldev, 0); 29348347601bSyl if (status != XGE_HAL_OK) 2935a23fd118Syl return status; 29368347601bSyl 2937a23fd118Syl status = __hal_device_rth_it_configure(hldev); 29388347601bSyl if (status != XGE_HAL_OK) 2939a23fd118Syl return status; 29408347601bSyl 2941a23fd118Syl status = __hal_device_rth_spdm_configure(hldev); 29428347601bSyl if (status != XGE_HAL_OK) 2943a23fd118Syl return status; 29448347601bSyl 2945a23fd118Syl status = __hal_device_rts_mac_configure(hldev); 2946a23fd118Syl if (status != XGE_HAL_OK) { 29477eced415Sxw xge_debug_device(XGE_ERR, "__hal_device_rts_mac_configure Failed "); 29487eced415Sxw return status; 29497eced415Sxw } 29507eced415Sxw 29517eced415Sxw status = __hal_device_rts_port_configure(hldev); 29527eced415Sxw if (status != XGE_HAL_OK) { 29537eced415Sxw xge_debug_device(XGE_ERR, "__hal_device_rts_port_configure Failed "); 2954a23fd118Syl return status; 2955a23fd118Syl } 2956a23fd118Syl 29578347601bSyl status = __hal_device_rts_qos_configure(hldev); 29588347601bSyl if (status != XGE_HAL_OK) { 29597eced415Sxw xge_debug_device(XGE_ERR, "__hal_device_rts_qos_configure Failed "); 29608347601bSyl return status; 29618347601bSyl } 29628347601bSyl 2963a23fd118Syl __hal_device_pause_frames_configure(hldev); 2964a23fd118Syl __hal_device_rmac_padding_configure(hldev); 2965a23fd118Syl __hal_device_shared_splits_configure(hldev); 2966a23fd118Syl 2967a23fd118Syl /* make sure all interrupts going to be disabled at the moment */ 2968a23fd118Syl __hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0); 2969a23fd118Syl 2970a23fd118Syl /* SXE-008 Transmit DMA arbitration issue */ 2971a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA && 2972a23fd118Syl hldev->revision < 4) { 2973a23fd118Syl xge_os_pio_mem_write64(hldev->pdev,hldev->regh0, 2974a23fd118Syl XGE_HAL_ADAPTER_PCC_ENABLE_FOUR, 2975a23fd118Syl &bar0->pcc_enable); 2976a23fd118Syl } 2977a23fd118Syl __hal_fifo_hw_initialize(hldev); 2978a23fd118Syl __hal_ring_hw_initialize(hldev); 2979a23fd118Syl 2980a23fd118Syl if (__hal_device_wait_quiescent(hldev, &val64)) { 2981a23fd118Syl return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 2982a23fd118Syl } 2983a23fd118Syl 2984a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1, 2985a23fd118Syl XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT, 2986a23fd118Syl XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 2987a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!"); 2988a23fd118Syl return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 2989a23fd118Syl } 2990a23fd118Syl 29918347601bSyl xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is quiescent", 2992a23fd118Syl (unsigned long long)(ulong_t)hldev); 2993a23fd118Syl 29947eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX || 29957eced415Sxw hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI) { 29967eced415Sxw /* 29977eced415Sxw * If MSI is enabled, ensure that One Shot for MSI in PCI_CTRL 29987eced415Sxw * is disabled. 29997eced415Sxw */ 30007eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 30017eced415Sxw &bar0->pic_control); 30027eced415Sxw val64 &= ~(XGE_HAL_PIC_CNTL_ONE_SHOT_TINT); 30037eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 30047eced415Sxw &bar0->pic_control); 30057eced415Sxw } 3006a23fd118Syl 3007a23fd118Syl hldev->hw_is_initialized = 1; 3008a23fd118Syl hldev->terminating = 0; 3009a23fd118Syl return XGE_HAL_OK; 3010a23fd118Syl } 3011a23fd118Syl 3012a23fd118Syl /* 3013a23fd118Syl * __hal_device_reset - Reset device only. 3014a23fd118Syl * @hldev: HAL device handle. 3015a23fd118Syl * 3016a23fd118Syl * Reset the device, and subsequently restore 3017a23fd118Syl * the previously saved PCI configuration space. 3018a23fd118Syl */ 30198347601bSyl #define XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT 50 3020a23fd118Syl static xge_hal_status_e 3021a23fd118Syl __hal_device_reset(xge_hal_device_t *hldev) 3022a23fd118Syl { 3023a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 30248347601bSyl int i, j, swap_done, pcisize = 0; 3025a23fd118Syl u64 val64, rawval = 0ULL; 3026a23fd118Syl 30277eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 30287eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 30297eced415Sxw if ( hldev->bar2 ) { 30307eced415Sxw u64 *msix_vetor_table = (u64 *)hldev->bar2; 30317eced415Sxw 30327eced415Sxw // 2 64bit words for each entry 30337eced415Sxw for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2; 30347eced415Sxw i++) { 30357eced415Sxw hldev->msix_vector_table[i] = 30367eced415Sxw xge_os_pio_mem_read64(hldev->pdev, 30377eced415Sxw hldev->regh2, &msix_vetor_table[i]); 30387eced415Sxw } 3039a23fd118Syl } 3040a23fd118Syl } 3041a23fd118Syl } 3042a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3043a23fd118Syl &bar0->pif_rd_swapper_fb); 3044a23fd118Syl swap_done = (val64 == XGE_HAL_IF_RD_SWAPPER_FB); 3045a23fd118Syl 3046a23fd118Syl if (swap_done) { 3047a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 3048a23fd118Syl (u32)(XGE_HAL_SW_RESET_ALL>>32), (char *)&bar0->sw_reset); 3049a23fd118Syl } else { 3050a23fd118Syl u32 val = (u32)(XGE_HAL_SW_RESET_ALL >> 32); 3051a23fd118Syl #if defined(XGE_OS_HOST_LITTLE_ENDIAN) || defined(XGE_OS_PIO_LITTLE_ENDIAN) 3052a23fd118Syl /* swap it */ 3053a23fd118Syl val = (((val & (u32)0x000000ffUL) << 24) | 3054a23fd118Syl ((val & (u32)0x0000ff00UL) << 8) | 3055a23fd118Syl ((val & (u32)0x00ff0000UL) >> 8) | 3056a23fd118Syl ((val & (u32)0xff000000UL) >> 24)); 3057a23fd118Syl #endif 3058a23fd118Syl xge_os_pio_mem_write32(hldev->pdev, hldev->regh0, val, 3059a23fd118Syl &bar0->sw_reset); 3060a23fd118Syl } 3061a23fd118Syl 30628347601bSyl pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)? 30638347601bSyl XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA; 30648347601bSyl 30658347601bSyl xge_os_mdelay(20); /* Wait for 20 ms after reset */ 30668347601bSyl 30678347601bSyl { 30688347601bSyl /* Poll for no more than 1 second */ 30698347601bSyl for (i = 0; i < XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT; i++) 30708347601bSyl { 30718347601bSyl for (j = 0; j < pcisize; j++) { 30728347601bSyl xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4, 30738347601bSyl *((u32*)&hldev->pci_config_space + j)); 30748347601bSyl } 30758347601bSyl 30768347601bSyl xge_os_pci_read16(hldev->pdev,hldev->cfgh, 30778347601bSyl xge_offsetof(xge_hal_pci_config_le_t, device_id), 30788347601bSyl &hldev->device_id); 30797eced415Sxw 30808347601bSyl if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_UNKNOWN) 30818347601bSyl break; 30828347601bSyl xge_os_mdelay(20); 30838347601bSyl } 30848347601bSyl } 30858347601bSyl 30868347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_UNKNOWN) 30878347601bSyl { 30888347601bSyl xge_debug_device(XGE_ERR, "device reset failed"); 30898347601bSyl return XGE_HAL_ERR_RESET_FAILED; 30908347601bSyl } 30918347601bSyl 3092a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 3093a23fd118Syl int cnt = 0; 3094a23fd118Syl 3095a23fd118Syl rawval = XGE_HAL_SW_RESET_RAW_VAL_HERC; 3096a23fd118Syl pcisize = XGE_HAL_PCISIZE_HERC; 3097a23fd118Syl xge_os_mdelay(1); 3098a23fd118Syl do { 3099a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3100a23fd118Syl &bar0->sw_reset); 3101a23fd118Syl if (val64 != rawval) { 3102a23fd118Syl break; 3103a23fd118Syl } 3104a23fd118Syl cnt++; 3105a23fd118Syl xge_os_mdelay(1); /* Wait for 1ms before retry */ 3106a23fd118Syl } while(cnt < 20); 3107a23fd118Syl } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 3108a23fd118Syl rawval = XGE_HAL_SW_RESET_RAW_VAL_XENA; 3109a23fd118Syl pcisize = XGE_HAL_PCISIZE_XENA; 3110a23fd118Syl xge_os_mdelay(XGE_HAL_DEVICE_RESET_WAIT_MAX_MILLIS); 3111a23fd118Syl } 3112a23fd118Syl 3113a23fd118Syl /* Restore MSI-X vector table */ 31147eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 31157eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 31167eced415Sxw if ( hldev->bar2 ) { 31177eced415Sxw /* 31187eced415Sxw * 94: MSIXTable 00000004 ( BIR:4 Offset:0x0 ) 31197eced415Sxw * 98: PBATable 00000404 ( BIR:4 Offset:0x400 ) 31207eced415Sxw */ 31217eced415Sxw u64 *msix_vetor_table = (u64 *)hldev->bar2; 31227eced415Sxw 31237eced415Sxw /* 2 64bit words for each entry */ 31247eced415Sxw for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2; 31257eced415Sxw i++) { 31267eced415Sxw xge_os_pio_mem_write64(hldev->pdev, 31277eced415Sxw hldev->regh2, 31287eced415Sxw hldev->msix_vector_table[i], 31297eced415Sxw &msix_vetor_table[i]); 31307eced415Sxw } 3131a23fd118Syl } 3132a23fd118Syl } 3133a23fd118Syl } 3134a23fd118Syl 3135a23fd118Syl hldev->link_state = XGE_HAL_LINK_DOWN; 3136a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3137a23fd118Syl &bar0->sw_reset); 3138a23fd118Syl 3139a23fd118Syl if (val64 != rawval) { 3140a23fd118Syl xge_debug_device(XGE_ERR, "device has not been reset " 31418347601bSyl "got 0x"XGE_OS_LLXFMT", expected 0x"XGE_OS_LLXFMT, 3142a23fd118Syl (unsigned long long)val64, (unsigned long long)rawval); 3143a23fd118Syl return XGE_HAL_ERR_RESET_FAILED; 3144a23fd118Syl } 3145a23fd118Syl 3146a23fd118Syl hldev->hw_is_initialized = 0; 3147a23fd118Syl return XGE_HAL_OK; 3148a23fd118Syl } 3149a23fd118Syl 3150a23fd118Syl /* 3151a23fd118Syl * __hal_device_poll - General private routine to poll the device. 3152a23fd118Syl * @hldev: HAL device handle. 3153a23fd118Syl * 3154a23fd118Syl * Returns: one of the xge_hal_status_e{} enumerated types. 3155a23fd118Syl * XGE_HAL_OK - for success. 3156a23fd118Syl * XGE_HAL_ERR_CRITICAL - when encounters critical error. 3157a23fd118Syl */ 3158a23fd118Syl static xge_hal_status_e 3159a23fd118Syl __hal_device_poll(xge_hal_device_t *hldev) 3160a23fd118Syl { 3161a23fd118Syl xge_hal_pci_bar0_t *bar0; 3162a23fd118Syl u64 err_reg; 3163a23fd118Syl 3164a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 3165a23fd118Syl 3166a23fd118Syl /* Handling SERR errors by forcing a H/W reset. */ 3167a23fd118Syl err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3168a23fd118Syl &bar0->serr_source); 3169a23fd118Syl if (err_reg & XGE_HAL_SERR_SOURCE_ANY) { 3170a23fd118Syl __hal_device_handle_serr(hldev, "serr_source", err_reg); 3171a23fd118Syl return XGE_HAL_ERR_CRITICAL; 3172a23fd118Syl } 3173a23fd118Syl 3174a23fd118Syl err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3175a23fd118Syl &bar0->misc_int_reg); 3176a23fd118Syl 3177a23fd118Syl if (err_reg & XGE_HAL_MISC_INT_REG_DP_ERR_INT) { 3178a23fd118Syl hldev->stats.sw_dev_err_stats.parity_err_cnt++; 3179a23fd118Syl __hal_device_handle_parityerr(hldev, "misc_int_reg", err_reg); 3180a23fd118Syl return XGE_HAL_ERR_CRITICAL; 3181a23fd118Syl } 3182a23fd118Syl 3183a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 31847eced415Sxw if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) || 31857eced415Sxw (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX)) 3186a23fd118Syl #endif 3187a23fd118Syl { 3188a23fd118Syl 3189a23fd118Syl /* Handling link status change error Intr */ 3190a23fd118Syl err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3191a23fd118Syl &bar0->mac_rmac_err_reg); 3192a23fd118Syl if (__hal_device_handle_link_state_change(hldev)) 3193a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3194a23fd118Syl err_reg, &bar0->mac_rmac_err_reg); 3195a23fd118Syl } 3196a23fd118Syl 3197a23fd118Syl if (hldev->inject_serr != 0) { 3198a23fd118Syl err_reg = hldev->inject_serr; 3199a23fd118Syl hldev->inject_serr = 0; 3200a23fd118Syl __hal_device_handle_serr(hldev, "inject_serr", err_reg); 3201a23fd118Syl return XGE_HAL_ERR_CRITICAL; 3202a23fd118Syl } 3203a23fd118Syl 3204a23fd118Syl if (hldev->inject_ecc != 0) { 3205a23fd118Syl err_reg = hldev->inject_ecc; 3206a23fd118Syl hldev->inject_ecc = 0; 3207a23fd118Syl hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 3208a23fd118Syl __hal_device_handle_eccerr(hldev, "inject_ecc", err_reg); 3209a23fd118Syl return XGE_HAL_ERR_CRITICAL; 3210a23fd118Syl } 3211a23fd118Syl 3212a23fd118Syl if (hldev->inject_bad_tcode != 0) { 3213a23fd118Syl u8 t_code = hldev->inject_bad_tcode; 3214a23fd118Syl xge_hal_channel_t channel; 3215a23fd118Syl xge_hal_fifo_txd_t txd; 3216a23fd118Syl xge_hal_ring_rxd_1_t rxd; 3217a23fd118Syl 3218a23fd118Syl channel.devh = hldev; 3219a23fd118Syl 3220a23fd118Syl if (hldev->inject_bad_tcode_for_chan_type == 3221a23fd118Syl XGE_HAL_CHANNEL_TYPE_FIFO) { 3222a23fd118Syl channel.type = XGE_HAL_CHANNEL_TYPE_FIFO; 3223a23fd118Syl 3224a23fd118Syl } else { 3225a23fd118Syl channel.type = XGE_HAL_CHANNEL_TYPE_RING; 3226a23fd118Syl } 3227a23fd118Syl 3228a23fd118Syl hldev->inject_bad_tcode = 0; 3229a23fd118Syl 3230a23fd118Syl if (channel.type == XGE_HAL_CHANNEL_TYPE_FIFO) 3231a23fd118Syl return xge_hal_device_handle_tcode(&channel, &txd, 3232a23fd118Syl t_code); 3233a23fd118Syl else 3234a23fd118Syl return xge_hal_device_handle_tcode(&channel, &rxd, 3235a23fd118Syl t_code); 3236a23fd118Syl } 3237a23fd118Syl 3238a23fd118Syl return XGE_HAL_OK; 3239a23fd118Syl } 3240a23fd118Syl 3241a23fd118Syl /* 3242a23fd118Syl * __hal_verify_pcc_idle - Verify All Enbled PCC are IDLE or not 3243a23fd118Syl * @hldev: HAL device handle. 3244a23fd118Syl * @adp_status: Adapter Status value 3245a23fd118Syl * Usage: See xge_hal_device_enable{}. 3246a23fd118Syl */ 3247a23fd118Syl xge_hal_status_e 3248a23fd118Syl __hal_verify_pcc_idle(xge_hal_device_t *hldev, u64 adp_status) 3249a23fd118Syl { 3250a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA && 3251a23fd118Syl hldev->revision < 4) { 3252a23fd118Syl /* 3253a23fd118Syl * For Xena 1,2,3 we enable only 4 PCCs Due to 3254a23fd118Syl * SXE-008 (Transmit DMA arbitration issue) 3255a23fd118Syl */ 3256a23fd118Syl if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) 3257a23fd118Syl != XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) { 3258a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 3259a23fd118Syl "PCC is not IDLE after adapter enabled!"); 3260a23fd118Syl return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 3261a23fd118Syl } 3262a23fd118Syl } else { 3263a23fd118Syl if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) != 3264a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) { 3265a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 3266a23fd118Syl "PCC is not IDLE after adapter enabled!"); 3267a23fd118Syl return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 3268a23fd118Syl } 3269a23fd118Syl } 3270a23fd118Syl return XGE_HAL_OK; 3271a23fd118Syl } 3272a23fd118Syl 32738347601bSyl static void 32748347601bSyl __hal_update_bimodal(xge_hal_device_t *hldev, int ring_no) 32758347601bSyl { 32768347601bSyl int tval, d, iwl_avg, len_avg, bytes_avg, bytes_hist, d_hist; 32778347601bSyl int iwl_rxcnt, iwl_txcnt, iwl_txavg, len_rxavg, iwl_rxavg, len_txavg; 32788347601bSyl int iwl_cnt, i; 32798347601bSyl 32808347601bSyl #define _HIST_SIZE 50 /* 0.5 sec history */ 32818347601bSyl #define _HIST_ADJ_TIMER 1 32828347601bSyl #define _STEP 2 32838347601bSyl 32848347601bSyl static int bytes_avg_history[_HIST_SIZE] = {0}; 32858347601bSyl static int d_avg_history[_HIST_SIZE] = {0}; 32868347601bSyl static int history_idx = 0; 32878347601bSyl static int pstep = 1; 32888347601bSyl static int hist_adj_timer = 0; 32898347601bSyl 32908347601bSyl /* 32918347601bSyl * tval - current value of this bimodal timer 32928347601bSyl */ 32938347601bSyl tval = hldev->bimodal_tti[ring_no].timer_val_us; 32948347601bSyl 32958347601bSyl /* 32968347601bSyl * d - how many interrupts we were getting since last 32978347601bSyl * bimodal timer tick. 32988347601bSyl */ 32998347601bSyl d = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt - 33008347601bSyl hldev->bimodal_intr_cnt; 33018347601bSyl 33028347601bSyl /* advance bimodal interrupt counter */ 33038347601bSyl hldev->bimodal_intr_cnt = 33048347601bSyl hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt; 33058347601bSyl 33068347601bSyl /* 33078347601bSyl * iwl_cnt - how many interrupts we've got since last 33088347601bSyl * bimodal timer tick. 33098347601bSyl */ 33108347601bSyl iwl_rxcnt = (hldev->irq_workload_rxcnt[ring_no] ? 33118347601bSyl hldev->irq_workload_rxcnt[ring_no] : 1); 33128347601bSyl iwl_txcnt = (hldev->irq_workload_txcnt[ring_no] ? 33138347601bSyl hldev->irq_workload_txcnt[ring_no] : 1); 33148347601bSyl iwl_cnt = iwl_rxcnt + iwl_txcnt; 33158347601bSyl iwl_cnt = iwl_cnt; /* just to remove the lint warning */ 33168347601bSyl 33178347601bSyl /* 33188347601bSyl * we need to take hldev->config.isr_polling_cnt into account 33198347601bSyl * but for some reason this line causing GCC to produce wrong 33208347601bSyl * code on Solaris. As of now, if bimodal_interrupts is configured 33218347601bSyl * hldev->config.isr_polling_cnt is forced to be "0". 33228347601bSyl * 33238347601bSyl * iwl_cnt = iwl_cnt / (hldev->config.isr_polling_cnt + 1); */ 33248347601bSyl 33258347601bSyl /* 33268347601bSyl * iwl_avg - how many RXDs on avarage been processed since 33278347601bSyl * last bimodal timer tick. This indirectly includes 33288347601bSyl * CPU utilizations. 33298347601bSyl */ 33308347601bSyl iwl_rxavg = hldev->irq_workload_rxd[ring_no] / iwl_rxcnt; 33318347601bSyl iwl_txavg = hldev->irq_workload_txd[ring_no] / iwl_txcnt; 33328347601bSyl iwl_avg = iwl_rxavg + iwl_txavg; 33338347601bSyl iwl_avg = iwl_avg == 0 ? 1 : iwl_avg; 33348347601bSyl 33358347601bSyl /* 33368347601bSyl * len_avg - how many bytes on avarage been processed since 33378347601bSyl * last bimodal timer tick. i.e. avarage frame size. 33388347601bSyl */ 33398347601bSyl len_rxavg = 1 + hldev->irq_workload_rxlen[ring_no] / 33408347601bSyl (hldev->irq_workload_rxd[ring_no] ? 33418347601bSyl hldev->irq_workload_rxd[ring_no] : 1); 33428347601bSyl len_txavg = 1 + hldev->irq_workload_txlen[ring_no] / 33438347601bSyl (hldev->irq_workload_txd[ring_no] ? 33448347601bSyl hldev->irq_workload_txd[ring_no] : 1); 33458347601bSyl len_avg = len_rxavg + len_txavg; 33468347601bSyl if (len_avg < 60) 33478347601bSyl len_avg = 60; 33488347601bSyl 33498347601bSyl /* align on low boundary */ 33508347601bSyl if ((tval -_STEP) < hldev->config.bimodal_timer_lo_us) 33518347601bSyl tval = hldev->config.bimodal_timer_lo_us; 33528347601bSyl 33538347601bSyl /* reset faster */ 33548347601bSyl if (iwl_avg == 1) { 33558347601bSyl tval = hldev->config.bimodal_timer_lo_us; 33568347601bSyl /* reset history */ 33578347601bSyl for (i = 0; i < _HIST_SIZE; i++) 33588347601bSyl bytes_avg_history[i] = d_avg_history[i] = 0; 33598347601bSyl history_idx = 0; 33608347601bSyl pstep = 1; 33618347601bSyl hist_adj_timer = 0; 33628347601bSyl } 33638347601bSyl 33648347601bSyl /* always try to ajust timer to the best throughput value */ 33658347601bSyl bytes_avg = iwl_avg * len_avg; 33668347601bSyl history_idx %= _HIST_SIZE; 33678347601bSyl bytes_avg_history[history_idx] = bytes_avg; 33688347601bSyl d_avg_history[history_idx] = d; 33698347601bSyl history_idx++; 33708347601bSyl d_hist = bytes_hist = 0; 33718347601bSyl for (i = 0; i < _HIST_SIZE; i++) { 33728347601bSyl /* do not re-configure until history is gathered */ 33738347601bSyl if (!bytes_avg_history[i]) { 33748347601bSyl tval = hldev->config.bimodal_timer_lo_us; 33758347601bSyl goto _end; 33768347601bSyl } 33778347601bSyl bytes_hist += bytes_avg_history[i]; 33788347601bSyl d_hist += d_avg_history[i]; 33798347601bSyl } 33808347601bSyl bytes_hist /= _HIST_SIZE; 33818347601bSyl d_hist /= _HIST_SIZE; 33828347601bSyl 33838347601bSyl // xge_os_printf("d %d iwl_avg %d len_avg %d:%d:%d tval %d avg %d hist %d pstep %d", 33848347601bSyl // d, iwl_avg, len_txavg, len_rxavg, len_avg, tval, d*bytes_avg, 33858347601bSyl // d_hist*bytes_hist, pstep); 33868347601bSyl 33878347601bSyl /* make an adaptive step */ 33888347601bSyl if (d * bytes_avg < d_hist * bytes_hist && hist_adj_timer++ > _HIST_ADJ_TIMER) { 33898347601bSyl pstep = !pstep; 33908347601bSyl hist_adj_timer = 0; 33918347601bSyl } 33928347601bSyl 33938347601bSyl if (pstep && 33948347601bSyl (tval + _STEP) <= hldev->config.bimodal_timer_hi_us) { 33958347601bSyl tval += _STEP; 33968347601bSyl hldev->stats.sw_dev_info_stats.bimodal_hi_adjust_cnt++; 33978347601bSyl } else if ((tval - _STEP) >= hldev->config.bimodal_timer_lo_us) { 33988347601bSyl tval -= _STEP; 33998347601bSyl hldev->stats.sw_dev_info_stats.bimodal_lo_adjust_cnt++; 34008347601bSyl } 34018347601bSyl 34028347601bSyl /* enable TTI range A for better latencies */ 34038347601bSyl hldev->bimodal_urange_a_en = 0; 34048347601bSyl if (tval <= hldev->config.bimodal_timer_lo_us && iwl_avg > 2) 34058347601bSyl hldev->bimodal_urange_a_en = 1; 34068347601bSyl 34078347601bSyl _end: 34088347601bSyl /* reset workload statistics counters */ 34098347601bSyl hldev->irq_workload_rxcnt[ring_no] = 0; 34108347601bSyl hldev->irq_workload_rxd[ring_no] = 0; 34118347601bSyl hldev->irq_workload_rxlen[ring_no] = 0; 34128347601bSyl hldev->irq_workload_txcnt[ring_no] = 0; 34138347601bSyl hldev->irq_workload_txd[ring_no] = 0; 34148347601bSyl hldev->irq_workload_txlen[ring_no] = 0; 34158347601bSyl 34168347601bSyl /* reconfigure TTI56 + ring_no with new timer value */ 34178347601bSyl hldev->bimodal_timer_val_us = tval; 34188347601bSyl (void) __hal_device_rti_configure(hldev, 1); 34198347601bSyl } 34208347601bSyl 3421a23fd118Syl static void 3422a23fd118Syl __hal_update_rxufca(xge_hal_device_t *hldev, int ring_no) 3423a23fd118Syl { 34248347601bSyl int ufc, ic, i; 34258347601bSyl 34268347601bSyl ufc = hldev->config.ring.queue[ring_no].rti.ufc_a; 34278347601bSyl ic = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt; 3428a23fd118Syl 3429a23fd118Syl /* urange_a adaptive coalescing */ 3430a23fd118Syl if (hldev->rxufca_lbolt > hldev->rxufca_lbolt_time) { 3431a23fd118Syl if (ic > hldev->rxufca_intr_thres) { 3432a23fd118Syl if (ufc < hldev->config.rxufca_hi_lim) { 3433a23fd118Syl ufc += 1; 3434a23fd118Syl for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) 3435a23fd118Syl hldev->config.ring.queue[i].rti.ufc_a = ufc; 3436a23fd118Syl (void) __hal_device_rti_configure(hldev, 1); 34377eced415Sxw hldev->stats.sw_dev_info_stats.rxufca_hi_adjust_cnt++; 3438a23fd118Syl } 3439a23fd118Syl hldev->rxufca_intr_thres = ic + 3440a23fd118Syl hldev->config.rxufca_intr_thres; /* def: 30 */ 3441a23fd118Syl } else { 3442a23fd118Syl if (ufc > hldev->config.rxufca_lo_lim) { 3443a23fd118Syl ufc -= 1; 3444a23fd118Syl for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) 3445a23fd118Syl hldev->config.ring.queue[i].rti.ufc_a = ufc; 3446a23fd118Syl (void) __hal_device_rti_configure(hldev, 1); 34477eced415Sxw hldev->stats.sw_dev_info_stats.rxufca_lo_adjust_cnt++; 3448a23fd118Syl } 3449a23fd118Syl } 3450a23fd118Syl hldev->rxufca_lbolt_time = hldev->rxufca_lbolt + 3451a23fd118Syl hldev->config.rxufca_lbolt_period; 3452a23fd118Syl } 3453a23fd118Syl hldev->rxufca_lbolt++; 3454a23fd118Syl } 3455a23fd118Syl 3456a23fd118Syl /* 3457a23fd118Syl * __hal_device_handle_mc - Handle MC interrupt reason 3458a23fd118Syl * @hldev: HAL device handle. 3459a23fd118Syl * @reason: interrupt reason 3460a23fd118Syl */ 3461a23fd118Syl xge_hal_status_e 3462a23fd118Syl __hal_device_handle_mc(xge_hal_device_t *hldev, u64 reason) 3463a23fd118Syl { 3464a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3465a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3466a23fd118Syl u64 val64; 3467a23fd118Syl 3468a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3469a23fd118Syl &isrbar0->mc_int_status); 3470a23fd118Syl if (!(val64 & XGE_HAL_MC_INT_STATUS_MC_INT)) 3471a23fd118Syl return XGE_HAL_OK; 3472a23fd118Syl 3473a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3474a23fd118Syl &isrbar0->mc_err_reg); 3475a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3476a23fd118Syl val64, &isrbar0->mc_err_reg); 3477a23fd118Syl 3478a23fd118Syl if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_L || 3479a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_U || 3480a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_0 || 3481a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_1 || 3482a23fd118Syl (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA && 3483a23fd118Syl (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_L || 3484a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_U || 3485a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_L || 3486a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_U))) { 3487a23fd118Syl hldev->stats.sw_dev_err_stats.single_ecc_err_cnt++; 3488a23fd118Syl hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 3489a23fd118Syl } 3490a23fd118Syl 3491a23fd118Syl if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_L || 3492a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_U || 3493a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 || 3494a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1 || 3495a23fd118Syl (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA && 3496a23fd118Syl (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_L || 3497a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_U || 3498a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_L || 3499a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_U))) { 3500a23fd118Syl hldev->stats.sw_dev_err_stats.double_ecc_err_cnt++; 3501a23fd118Syl hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 3502a23fd118Syl } 3503a23fd118Syl 3504a23fd118Syl if (val64 & XGE_HAL_MC_ERR_REG_SM_ERR) { 3505a23fd118Syl hldev->stats.sw_dev_err_stats.sm_err_cnt++; 3506a23fd118Syl } 3507a23fd118Syl 3508a23fd118Syl /* those two should result in device reset */ 3509a23fd118Syl if (val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 || 3510a23fd118Syl val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1) { 3511a23fd118Syl __hal_device_handle_eccerr(hldev, "mc_err_reg", val64); 3512a23fd118Syl return XGE_HAL_ERR_CRITICAL; 3513a23fd118Syl } 3514a23fd118Syl 3515a23fd118Syl return XGE_HAL_OK; 3516a23fd118Syl } 3517a23fd118Syl 3518a23fd118Syl /* 3519a23fd118Syl * __hal_device_handle_pic - Handle non-traffic PIC interrupt reason 3520a23fd118Syl * @hldev: HAL device handle. 3521a23fd118Syl * @reason: interrupt reason 3522a23fd118Syl */ 3523a23fd118Syl xge_hal_status_e 3524a23fd118Syl __hal_device_handle_pic(xge_hal_device_t *hldev, u64 reason) 3525a23fd118Syl { 3526a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3527a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3528a23fd118Syl u64 val64; 3529a23fd118Syl 3530a23fd118Syl if (reason & XGE_HAL_PIC_INT_FLSH) { 3531a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3532a23fd118Syl &isrbar0->flsh_int_reg); 3533a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3534a23fd118Syl val64, &isrbar0->flsh_int_reg); 3535a23fd118Syl /* FIXME: handle register */ 3536a23fd118Syl } 3537a23fd118Syl if (reason & XGE_HAL_PIC_INT_MDIO) { 3538a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3539a23fd118Syl &isrbar0->mdio_int_reg); 3540a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3541a23fd118Syl val64, &isrbar0->mdio_int_reg); 3542a23fd118Syl /* FIXME: handle register */ 3543a23fd118Syl } 3544a23fd118Syl if (reason & XGE_HAL_PIC_INT_IIC) { 3545a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3546a23fd118Syl &isrbar0->iic_int_reg); 3547a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3548a23fd118Syl val64, &isrbar0->iic_int_reg); 3549a23fd118Syl /* FIXME: handle register */ 3550a23fd118Syl } 3551a23fd118Syl if (reason & XGE_HAL_PIC_INT_MISC) { 3552a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, 3553a23fd118Syl hldev->regh0, &isrbar0->misc_int_reg); 3554a23fd118Syl #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 35557eced415Sxw if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) && 35567eced415Sxw (hldev->config.intr_mode != XGE_HAL_INTR_MODE_MSIX)) { 3557a23fd118Syl /* Check for Link interrupts. If both Link Up/Down 3558a23fd118Syl * bits are set, clear both and check adapter status 3559a23fd118Syl */ 3560a23fd118Syl if ((val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) && 3561a23fd118Syl (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT)) { 3562a23fd118Syl u64 temp64; 3563a23fd118Syl 3564a23fd118Syl xge_debug_device(XGE_TRACE, 35658347601bSyl "both link up and link down detected "XGE_OS_LLXFMT, 3566a23fd118Syl (unsigned long long)val64); 3567a23fd118Syl 3568a23fd118Syl temp64 = (XGE_HAL_MISC_INT_REG_LINK_DOWN_INT | 3569a23fd118Syl XGE_HAL_MISC_INT_REG_LINK_UP_INT); 3570a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 3571a23fd118Syl hldev->regh0, temp64, 3572a23fd118Syl &isrbar0->misc_int_reg); 3573a23fd118Syl } 3574a23fd118Syl else if (val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) { 3575a23fd118Syl xge_debug_device(XGE_TRACE, 35768347601bSyl "link up call request, misc_int "XGE_OS_LLXFMT, 3577a23fd118Syl (unsigned long long)val64); 3578a23fd118Syl __hal_device_handle_link_up_ind(hldev); 3579a23fd118Syl } 3580a23fd118Syl else if (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT){ 3581a23fd118Syl xge_debug_device(XGE_TRACE, 35828347601bSyl "link down request, misc_int "XGE_OS_LLXFMT, 3583a23fd118Syl (unsigned long long)val64); 3584a23fd118Syl __hal_device_handle_link_down_ind(hldev); 3585a23fd118Syl } 3586a23fd118Syl } else 3587a23fd118Syl #endif 3588a23fd118Syl { 3589a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3590a23fd118Syl val64, &isrbar0->misc_int_reg); 3591a23fd118Syl } 3592a23fd118Syl } 3593a23fd118Syl 3594a23fd118Syl return XGE_HAL_OK; 3595a23fd118Syl } 3596a23fd118Syl 3597a23fd118Syl /* 3598a23fd118Syl * __hal_device_handle_txpic - Handle TxPIC interrupt reason 3599a23fd118Syl * @hldev: HAL device handle. 3600a23fd118Syl * @reason: interrupt reason 3601a23fd118Syl */ 3602a23fd118Syl xge_hal_status_e 3603a23fd118Syl __hal_device_handle_txpic(xge_hal_device_t *hldev, u64 reason) 3604a23fd118Syl { 3605a23fd118Syl xge_hal_status_e status = XGE_HAL_OK; 3606a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3607a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 3608a23fd118Syl volatile u64 val64; 3609a23fd118Syl 3610a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3611a23fd118Syl &isrbar0->pic_int_status); 3612a23fd118Syl if ( val64 & (XGE_HAL_PIC_INT_FLSH | 3613a23fd118Syl XGE_HAL_PIC_INT_MDIO | 3614a23fd118Syl XGE_HAL_PIC_INT_IIC | 3615a23fd118Syl XGE_HAL_PIC_INT_MISC) ) { 3616a23fd118Syl status = __hal_device_handle_pic(hldev, val64); 3617a23fd118Syl xge_os_wmb(); 3618a23fd118Syl } 3619a23fd118Syl 3620a23fd118Syl if (!(val64 & XGE_HAL_PIC_INT_TX)) 3621a23fd118Syl return status; 3622a23fd118Syl 3623a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3624a23fd118Syl &isrbar0->txpic_int_reg); 3625a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3626a23fd118Syl val64, &isrbar0->txpic_int_reg); 3627a23fd118Syl xge_os_wmb(); 3628a23fd118Syl 3629a23fd118Syl if (val64 & XGE_HAL_TXPIC_INT_SCHED_INTR) { 3630a23fd118Syl int i; 3631a23fd118Syl 3632a23fd118Syl if (g_xge_hal_driver->uld_callbacks.sched_timer != NULL) 3633a23fd118Syl g_xge_hal_driver->uld_callbacks.sched_timer( 3634a23fd118Syl hldev, hldev->upper_layer_info); 3635a23fd118Syl /* 36368347601bSyl * This feature implements adaptive receive interrupt 3637a23fd118Syl * coalecing. It is disabled by default. To enable it 3638a23fd118Syl * set hldev->config.rxufca_lo_lim to be not equal to 3639a23fd118Syl * hldev->config.rxufca_hi_lim. 3640a23fd118Syl * 3641a23fd118Syl * We are using HW timer for this feature, so 3642a23fd118Syl * use needs to configure hldev->config.rxufca_lbolt_period 3643a23fd118Syl * which is essentially a time slice of timer. 3644a23fd118Syl * 3645a23fd118Syl * For those who familiar with Linux, lbolt means jiffies 3646a23fd118Syl * of this timer. I.e. timer tick. 3647a23fd118Syl */ 36488347601bSyl if (hldev->config.rxufca_lo_lim != 36498347601bSyl hldev->config.rxufca_hi_lim && 36508347601bSyl hldev->config.rxufca_lo_lim != 0) { 36518347601bSyl for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 36528347601bSyl if (!hldev->config.ring.queue[i].configured) 36538347601bSyl continue; 36548347601bSyl if (hldev->config.ring.queue[i].rti.urange_a) 3655a23fd118Syl __hal_update_rxufca(hldev, i); 3656a23fd118Syl } 3657a23fd118Syl } 36588347601bSyl 36598347601bSyl /* 36608347601bSyl * This feature implements adaptive TTI timer re-calculation 36618347601bSyl * based on host utilization, number of interrupt processed, 36628347601bSyl * number of RXD per tick and avarage length of packets per 36638347601bSyl * tick. 36648347601bSyl */ 36658347601bSyl if (hldev->config.bimodal_interrupts) { 36668347601bSyl for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 36678347601bSyl if (!hldev->config.ring.queue[i].configured) 36688347601bSyl continue; 36698347601bSyl if (hldev->bimodal_tti[i].enabled) 36708347601bSyl __hal_update_bimodal(hldev, i); 36718347601bSyl } 36728347601bSyl } 3673a23fd118Syl } 3674a23fd118Syl 3675a23fd118Syl return XGE_HAL_OK; 3676a23fd118Syl } 3677a23fd118Syl 3678a23fd118Syl /* 3679a23fd118Syl * __hal_device_handle_txdma - Handle TxDMA interrupt reason 3680a23fd118Syl * @hldev: HAL device handle. 3681a23fd118Syl * @reason: interrupt reason 3682a23fd118Syl */ 3683a23fd118Syl xge_hal_status_e 3684a23fd118Syl __hal_device_handle_txdma(xge_hal_device_t *hldev, u64 reason) 3685a23fd118Syl { 3686a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3687a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 36887eced415Sxw u64 val64, temp64, err; 3689a23fd118Syl 3690a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3691a23fd118Syl &isrbar0->txdma_int_status); 3692a23fd118Syl if (val64 & XGE_HAL_TXDMA_PFC_INT) { 3693a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3694a23fd118Syl &isrbar0->pfc_err_reg); 3695a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3696a23fd118Syl err, &isrbar0->pfc_err_reg); 36977eced415Sxw hldev->stats.sw_dev_info_stats.pfc_err_cnt++; 36987eced415Sxw temp64 = XGE_HAL_PFC_ECC_DB_ERR|XGE_HAL_PFC_SM_ERR_ALARM 36997eced415Sxw |XGE_HAL_PFC_MISC_0_ERR|XGE_HAL_PFC_MISC_1_ERR 37007eced415Sxw |XGE_HAL_PFC_PCIX_ERR; 37017eced415Sxw if (val64 & temp64) 37027eced415Sxw goto reset; 3703a23fd118Syl } 3704a23fd118Syl if (val64 & XGE_HAL_TXDMA_TDA_INT) { 3705a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3706a23fd118Syl &isrbar0->tda_err_reg); 3707a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3708a23fd118Syl err, &isrbar0->tda_err_reg); 37097eced415Sxw hldev->stats.sw_dev_info_stats.tda_err_cnt++; 37107eced415Sxw temp64 = XGE_HAL_TDA_Fn_ECC_DB_ERR|XGE_HAL_TDA_SM0_ERR_ALARM 37117eced415Sxw |XGE_HAL_TDA_SM1_ERR_ALARM; 37127eced415Sxw if (val64 & temp64) 37137eced415Sxw goto reset; 3714a23fd118Syl } 3715a23fd118Syl if (val64 & XGE_HAL_TXDMA_PCC_INT) { 3716a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3717a23fd118Syl &isrbar0->pcc_err_reg); 3718a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3719a23fd118Syl err, &isrbar0->pcc_err_reg); 37207eced415Sxw hldev->stats.sw_dev_info_stats.pcc_err_cnt++; 37217eced415Sxw temp64 = XGE_HAL_PCC_FB_ECC_DB_ERR|XGE_HAL_PCC_TXB_ECC_DB_ERR 37227eced415Sxw |XGE_HAL_PCC_SM_ERR_ALARM|XGE_HAL_PCC_WR_ERR_ALARM 37237eced415Sxw |XGE_HAL_PCC_N_SERR|XGE_HAL_PCC_6_COF_OV_ERR 37247eced415Sxw |XGE_HAL_PCC_7_COF_OV_ERR|XGE_HAL_PCC_6_LSO_OV_ERR 37257eced415Sxw |XGE_HAL_PCC_7_LSO_OV_ERR; 37267eced415Sxw if (val64 & temp64) 37277eced415Sxw goto reset; 3728a23fd118Syl } 3729a23fd118Syl if (val64 & XGE_HAL_TXDMA_TTI_INT) { 3730a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3731a23fd118Syl &isrbar0->tti_err_reg); 3732a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3733a23fd118Syl err, &isrbar0->tti_err_reg); 37347eced415Sxw hldev->stats.sw_dev_info_stats.tti_err_cnt++; 37357eced415Sxw temp64 = XGE_HAL_TTI_SM_ERR_ALARM; 37367eced415Sxw if (val64 & temp64) 37377eced415Sxw goto reset; 3738a23fd118Syl } 3739a23fd118Syl if (val64 & XGE_HAL_TXDMA_LSO_INT) { 3740a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3741a23fd118Syl &isrbar0->lso_err_reg); 3742a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3743a23fd118Syl err, &isrbar0->lso_err_reg); 37447eced415Sxw hldev->stats.sw_dev_info_stats.lso_err_cnt++; 37457eced415Sxw temp64 = XGE_HAL_LSO6_ABORT|XGE_HAL_LSO7_ABORT 37467eced415Sxw |XGE_HAL_LSO6_SM_ERR_ALARM|XGE_HAL_LSO7_SM_ERR_ALARM; 37477eced415Sxw if (val64 & temp64) 37487eced415Sxw goto reset; 3749a23fd118Syl } 3750a23fd118Syl if (val64 & XGE_HAL_TXDMA_TPA_INT) { 3751a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3752a23fd118Syl &isrbar0->tpa_err_reg); 3753a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3754a23fd118Syl err, &isrbar0->tpa_err_reg); 37557eced415Sxw hldev->stats.sw_dev_info_stats.tpa_err_cnt++; 37567eced415Sxw temp64 = XGE_HAL_TPA_SM_ERR_ALARM; 37577eced415Sxw if (val64 & temp64) 37587eced415Sxw goto reset; 3759a23fd118Syl } 3760a23fd118Syl if (val64 & XGE_HAL_TXDMA_SM_INT) { 3761a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3762a23fd118Syl &isrbar0->sm_err_reg); 3763a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3764a23fd118Syl err, &isrbar0->sm_err_reg); 37657eced415Sxw hldev->stats.sw_dev_info_stats.sm_err_cnt++; 37667eced415Sxw temp64 = XGE_HAL_SM_SM_ERR_ALARM; 37677eced415Sxw if (val64 & temp64) 37687eced415Sxw goto reset; 3769a23fd118Syl } 3770a23fd118Syl 3771a23fd118Syl return XGE_HAL_OK; 37727eced415Sxw 37737eced415Sxw reset : (void) xge_hal_device_reset(hldev); 37747eced415Sxw (void) xge_hal_device_enable(hldev); 37757eced415Sxw xge_hal_device_intr_enable(hldev); 37767eced415Sxw return XGE_HAL_OK; 3777a23fd118Syl } 3778a23fd118Syl 3779a23fd118Syl /* 3780a23fd118Syl * __hal_device_handle_txmac - Handle TxMAC interrupt reason 3781a23fd118Syl * @hldev: HAL device handle. 3782a23fd118Syl * @reason: interrupt reason 3783a23fd118Syl */ 3784a23fd118Syl xge_hal_status_e 3785a23fd118Syl __hal_device_handle_txmac(xge_hal_device_t *hldev, u64 reason) 3786a23fd118Syl { 3787a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3788a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 37897eced415Sxw u64 val64, temp64; 3790a23fd118Syl 3791a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3792a23fd118Syl &isrbar0->mac_int_status); 3793a23fd118Syl if (!(val64 & XGE_HAL_MAC_INT_STATUS_TMAC_INT)) 3794a23fd118Syl return XGE_HAL_OK; 3795a23fd118Syl 3796a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3797a23fd118Syl &isrbar0->mac_tmac_err_reg); 3798a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3799a23fd118Syl val64, &isrbar0->mac_tmac_err_reg); 38007eced415Sxw hldev->stats.sw_dev_info_stats.mac_tmac_err_cnt++; 38017eced415Sxw temp64 = XGE_HAL_TMAC_TX_BUF_OVRN|XGE_HAL_TMAC_TX_SM_ERR; 38027eced415Sxw if (val64 & temp64) { 38037eced415Sxw (void) xge_hal_device_reset(hldev); 38047eced415Sxw (void) xge_hal_device_enable(hldev); 38057eced415Sxw xge_hal_device_intr_enable(hldev); 38067eced415Sxw } 3807a23fd118Syl 3808a23fd118Syl return XGE_HAL_OK; 3809a23fd118Syl } 3810a23fd118Syl 3811a23fd118Syl /* 3812a23fd118Syl * __hal_device_handle_txxgxs - Handle TxXGXS interrupt reason 3813a23fd118Syl * @hldev: HAL device handle. 3814a23fd118Syl * @reason: interrupt reason 3815a23fd118Syl */ 3816a23fd118Syl xge_hal_status_e 3817a23fd118Syl __hal_device_handle_txxgxs(xge_hal_device_t *hldev, u64 reason) 3818a23fd118Syl { 38197eced415Sxw xge_hal_pci_bar0_t *isrbar0 = 38207eced415Sxw (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 38217eced415Sxw u64 val64, temp64; 38227eced415Sxw 38237eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 38247eced415Sxw &isrbar0->xgxs_int_status); 38257eced415Sxw if (!(val64 & XGE_HAL_XGXS_INT_STATUS_TXGXS)) 38267eced415Sxw return XGE_HAL_OK; 38277eced415Sxw 38287eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 38297eced415Sxw &isrbar0->xgxs_txgxs_err_reg); 38307eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 38317eced415Sxw val64, &isrbar0->xgxs_txgxs_err_reg); 38327eced415Sxw hldev->stats.sw_dev_info_stats.xgxs_txgxs_err_cnt++; 38337eced415Sxw temp64 = XGE_HAL_TXGXS_ESTORE_UFLOW|XGE_HAL_TXGXS_TX_SM_ERR; 38347eced415Sxw if (val64 & temp64) { 38357eced415Sxw (void) xge_hal_device_reset(hldev); 38367eced415Sxw (void) xge_hal_device_enable(hldev); 38377eced415Sxw xge_hal_device_intr_enable(hldev); 38387eced415Sxw } 3839a23fd118Syl 3840a23fd118Syl return XGE_HAL_OK; 3841a23fd118Syl } 3842a23fd118Syl 3843a23fd118Syl /* 3844a23fd118Syl * __hal_device_handle_rxpic - Handle RxPIC interrupt reason 3845a23fd118Syl * @hldev: HAL device handle. 3846a23fd118Syl * @reason: interrupt reason 3847a23fd118Syl */ 3848a23fd118Syl xge_hal_status_e 3849a23fd118Syl __hal_device_handle_rxpic(xge_hal_device_t *hldev, u64 reason) 3850a23fd118Syl { 3851a23fd118Syl /* FIXME: handle register */ 3852a23fd118Syl 3853a23fd118Syl return XGE_HAL_OK; 3854a23fd118Syl } 3855a23fd118Syl 3856a23fd118Syl /* 3857a23fd118Syl * __hal_device_handle_rxdma - Handle RxDMA interrupt reason 3858a23fd118Syl * @hldev: HAL device handle. 3859a23fd118Syl * @reason: interrupt reason 3860a23fd118Syl */ 3861a23fd118Syl xge_hal_status_e 3862a23fd118Syl __hal_device_handle_rxdma(xge_hal_device_t *hldev, u64 reason) 3863a23fd118Syl { 3864a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3865a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 38667eced415Sxw u64 val64, err, temp64; 3867a23fd118Syl 3868a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3869a23fd118Syl &isrbar0->rxdma_int_status); 3870a23fd118Syl if (val64 & XGE_HAL_RXDMA_RC_INT) { 3871a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3872a23fd118Syl &isrbar0->rc_err_reg); 3873a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3874a23fd118Syl err, &isrbar0->rc_err_reg); 38757eced415Sxw hldev->stats.sw_dev_info_stats.rc_err_cnt++; 38767eced415Sxw temp64 = XGE_HAL_RC_PRCn_ECC_DB_ERR|XGE_HAL_RC_FTC_ECC_DB_ERR 38777eced415Sxw |XGE_HAL_RC_PRCn_SM_ERR_ALARM 38787eced415Sxw |XGE_HAL_RC_FTC_SM_ERR_ALARM; 38797eced415Sxw if (val64 & temp64) 38807eced415Sxw goto reset; 3881a23fd118Syl } 3882a23fd118Syl if (val64 & XGE_HAL_RXDMA_RPA_INT) { 3883a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3884a23fd118Syl &isrbar0->rpa_err_reg); 3885a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3886a23fd118Syl err, &isrbar0->rpa_err_reg); 38877eced415Sxw hldev->stats.sw_dev_info_stats.rpa_err_cnt++; 38887eced415Sxw temp64 = XGE_HAL_RPA_SM_ERR_ALARM|XGE_HAL_RPA_CREDIT_ERR; 38897eced415Sxw if (val64 & temp64) 38907eced415Sxw goto reset; 3891a23fd118Syl } 3892a23fd118Syl if (val64 & XGE_HAL_RXDMA_RDA_INT) { 3893a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3894a23fd118Syl &isrbar0->rda_err_reg); 3895a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3896a23fd118Syl err, &isrbar0->rda_err_reg); 38977eced415Sxw hldev->stats.sw_dev_info_stats.rda_err_cnt++; 38987eced415Sxw temp64 = XGE_HAL_RDA_RXDn_ECC_DB_ERR 38997eced415Sxw |XGE_HAL_RDA_FRM_ECC_DB_N_AERR 39007eced415Sxw |XGE_HAL_RDA_SM1_ERR_ALARM|XGE_HAL_RDA_SM0_ERR_ALARM 39017eced415Sxw |XGE_HAL_RDA_RXD_ECC_DB_SERR; 39027eced415Sxw if (val64 & temp64) 39037eced415Sxw goto reset; 3904a23fd118Syl } 3905a23fd118Syl if (val64 & XGE_HAL_RXDMA_RTI_INT) { 3906a23fd118Syl err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3907a23fd118Syl &isrbar0->rti_err_reg); 3908a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3909a23fd118Syl err, &isrbar0->rti_err_reg); 39107eced415Sxw hldev->stats.sw_dev_info_stats.rti_err_cnt++; 39117eced415Sxw temp64 = XGE_HAL_RTI_SM_ERR_ALARM; 39127eced415Sxw if (val64 & temp64) 39137eced415Sxw goto reset; 3914a23fd118Syl } 3915a23fd118Syl 3916a23fd118Syl return XGE_HAL_OK; 39177eced415Sxw 39187eced415Sxw reset : (void) xge_hal_device_reset(hldev); 39197eced415Sxw (void) xge_hal_device_enable(hldev); 39207eced415Sxw xge_hal_device_intr_enable(hldev); 39217eced415Sxw return XGE_HAL_OK; 3922a23fd118Syl } 3923a23fd118Syl 3924a23fd118Syl /* 3925a23fd118Syl * __hal_device_handle_rxmac - Handle RxMAC interrupt reason 3926a23fd118Syl * @hldev: HAL device handle. 3927a23fd118Syl * @reason: interrupt reason 3928a23fd118Syl */ 3929a23fd118Syl xge_hal_status_e 3930a23fd118Syl __hal_device_handle_rxmac(xge_hal_device_t *hldev, u64 reason) 3931a23fd118Syl { 3932a23fd118Syl xge_hal_pci_bar0_t *isrbar0 = 3933a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 39347eced415Sxw u64 val64, temp64; 3935a23fd118Syl 3936a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3937a23fd118Syl &isrbar0->mac_int_status); 3938a23fd118Syl if (!(val64 & XGE_HAL_MAC_INT_STATUS_RMAC_INT)) 3939a23fd118Syl return XGE_HAL_OK; 3940a23fd118Syl 3941a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 3942a23fd118Syl &isrbar0->mac_rmac_err_reg); 3943a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 3944a23fd118Syl val64, &isrbar0->mac_rmac_err_reg); 39457eced415Sxw hldev->stats.sw_dev_info_stats.mac_rmac_err_cnt++; 39467eced415Sxw temp64 = XGE_HAL_RMAC_RX_BUFF_OVRN|XGE_HAL_RMAC_RX_SM_ERR; 39477eced415Sxw if (val64 & temp64) { 39487eced415Sxw (void) xge_hal_device_reset(hldev); 39497eced415Sxw (void) xge_hal_device_enable(hldev); 39507eced415Sxw xge_hal_device_intr_enable(hldev); 39517eced415Sxw } 3952a23fd118Syl 3953a23fd118Syl return XGE_HAL_OK; 3954a23fd118Syl } 3955a23fd118Syl 3956a23fd118Syl /* 3957a23fd118Syl * __hal_device_handle_rxxgxs - Handle RxXGXS interrupt reason 3958a23fd118Syl * @hldev: HAL device handle. 3959a23fd118Syl * @reason: interrupt reason 3960a23fd118Syl */ 3961a23fd118Syl xge_hal_status_e 3962a23fd118Syl __hal_device_handle_rxxgxs(xge_hal_device_t *hldev, u64 reason) 3963a23fd118Syl { 39647eced415Sxw xge_hal_pci_bar0_t *isrbar0 = 39657eced415Sxw (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0; 39667eced415Sxw u64 val64, temp64; 39677eced415Sxw 39687eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 39697eced415Sxw &isrbar0->xgxs_int_status); 39707eced415Sxw if (!(val64 & XGE_HAL_XGXS_INT_STATUS_RXGXS)) 39717eced415Sxw return XGE_HAL_OK; 39727eced415Sxw 39737eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 39747eced415Sxw &isrbar0->xgxs_rxgxs_err_reg); 39757eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 39767eced415Sxw val64, &isrbar0->xgxs_rxgxs_err_reg); 39777eced415Sxw hldev->stats.sw_dev_info_stats.xgxs_rxgxs_err_cnt++; 39787eced415Sxw temp64 = XGE_HAL_RXGXS_ESTORE_OFLOW|XGE_HAL_RXGXS_RX_SM_ERR; 39797eced415Sxw if (val64 & temp64) { 39807eced415Sxw (void) xge_hal_device_reset(hldev); 39817eced415Sxw (void) xge_hal_device_enable(hldev); 39827eced415Sxw xge_hal_device_intr_enable(hldev); 39837eced415Sxw } 3984a23fd118Syl 3985a23fd118Syl return XGE_HAL_OK; 3986a23fd118Syl } 3987a23fd118Syl 3988a23fd118Syl /** 3989a23fd118Syl * xge_hal_device_enable - Enable device. 3990a23fd118Syl * @hldev: HAL device handle. 3991a23fd118Syl * 3992a23fd118Syl * Enable the specified device: bring up the link/interface. 3993a23fd118Syl * Returns: XGE_HAL_OK - success. 3994a23fd118Syl * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device 3995a23fd118Syl * to a "quiescent" state. 3996a23fd118Syl * 3997a23fd118Syl * See also: xge_hal_status_e{}. 3998a23fd118Syl * 3999a23fd118Syl * Usage: See ex_open{}. 4000a23fd118Syl */ 4001a23fd118Syl xge_hal_status_e 4002a23fd118Syl xge_hal_device_enable(xge_hal_device_t *hldev) 4003a23fd118Syl { 4004a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4005a23fd118Syl u64 val64; 4006a23fd118Syl u64 adp_status; 4007a23fd118Syl int i, j; 4008a23fd118Syl 4009a23fd118Syl if (!hldev->hw_is_initialized) { 4010a23fd118Syl xge_hal_status_e status; 4011a23fd118Syl 4012a23fd118Syl status = __hal_device_hw_initialize(hldev); 4013a23fd118Syl if (status != XGE_HAL_OK) { 4014a23fd118Syl return status; 4015a23fd118Syl } 4016a23fd118Syl } 4017a23fd118Syl 4018a23fd118Syl /* 4019a23fd118Syl * Not needed in most cases, i.e. 4020a23fd118Syl * when device_disable() is followed by reset - 4021a23fd118Syl * the latter copies back PCI config space, along with 4022a23fd118Syl * the bus mastership - see __hal_device_reset(). 4023a23fd118Syl * However, there are/may-in-future be other cases, and 4024a23fd118Syl * does not hurt. 4025a23fd118Syl */ 4026a23fd118Syl __hal_device_bus_master_enable(hldev); 4027a23fd118Syl 4028a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 4029a23fd118Syl /* 4030a23fd118Syl * Configure the link stability period. 4031a23fd118Syl */ 4032a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4033a23fd118Syl &bar0->misc_control); 4034a23fd118Syl if (hldev->config.link_stability_period != 4035a23fd118Syl XGE_HAL_DEFAULT_USE_HARDCODE) { 4036a23fd118Syl 4037a23fd118Syl val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD( 4038a23fd118Syl hldev->config.link_stability_period); 4039a23fd118Syl } else { 4040a23fd118Syl /* 4041a23fd118Syl * Use the link stability period 1 ms as default 4042a23fd118Syl */ 4043a23fd118Syl val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD( 4044a23fd118Syl XGE_HAL_DEFAULT_LINK_STABILITY_PERIOD); 4045a23fd118Syl } 4046a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4047a23fd118Syl val64, &bar0->misc_control); 4048a23fd118Syl 4049a23fd118Syl /* 4050a23fd118Syl * Clearing any possible Link up/down interrupts that 4051a23fd118Syl * could have popped up just before Enabling the card. 4052a23fd118Syl */ 4053a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4054a23fd118Syl &bar0->misc_int_reg); 4055a23fd118Syl if (val64) { 4056a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4057a23fd118Syl val64, &bar0->misc_int_reg); 4058a23fd118Syl xge_debug_device(XGE_TRACE, "%s","link state cleared"); 4059a23fd118Syl } 4060a23fd118Syl } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 4061a23fd118Syl /* 4062a23fd118Syl * Clearing any possible Link state change interrupts that 4063a23fd118Syl * could have popped up just before Enabling the card. 4064a23fd118Syl */ 4065a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4066a23fd118Syl &bar0->mac_rmac_err_reg); 4067a23fd118Syl if (val64) { 4068a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4069a23fd118Syl val64, &bar0->mac_rmac_err_reg); 4070a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "link state cleared"); 4071a23fd118Syl } 4072a23fd118Syl } 4073a23fd118Syl 4074a23fd118Syl if (__hal_device_wait_quiescent(hldev, &val64)) { 4075a23fd118Syl return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4076a23fd118Syl } 4077a23fd118Syl 4078a23fd118Syl /* Enabling Laser. */ 4079a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4080a23fd118Syl &bar0->adapter_control); 4081a23fd118Syl val64 |= XGE_HAL_ADAPTER_EOI_TX_ON; 4082a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4083a23fd118Syl &bar0->adapter_control); 4084a23fd118Syl 4085a23fd118Syl /* let link establish */ 4086a23fd118Syl xge_os_mdelay(1); 4087a23fd118Syl 4088a23fd118Syl /* set link down untill poll() routine will set it up (maybe) */ 4089a23fd118Syl hldev->link_state = XGE_HAL_LINK_DOWN; 4090a23fd118Syl 4091a23fd118Syl /* If link is UP (adpter is connected) then enable the adapter */ 4092a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4093a23fd118Syl &bar0->adapter_status); 4094a23fd118Syl if( val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 4095a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT) ) { 4096a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4097a23fd118Syl &bar0->adapter_control); 4098a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); 4099a23fd118Syl } else { 4100a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4101a23fd118Syl &bar0->adapter_control); 4102a23fd118Syl val64 = val64 | ( XGE_HAL_ADAPTER_EOI_TX_ON | 4103a23fd118Syl XGE_HAL_ADAPTER_LED_ON ); 4104a23fd118Syl } 4105a23fd118Syl 4106a23fd118Syl val64 = val64 | XGE_HAL_ADAPTER_CNTL_EN; /* adapter enable */ 4107a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */ 4108a23fd118Syl xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, val64, 4109a23fd118Syl &bar0->adapter_control); 4110a23fd118Syl 4111a23fd118Syl /* We spin here waiting for the Link to come up. 4112a23fd118Syl * This is the fix for the Link being unstable after the reset. */ 4113a23fd118Syl i = 0; 4114a23fd118Syl j = 0; 4115a23fd118Syl do 4116a23fd118Syl { 4117a23fd118Syl adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4118a23fd118Syl &bar0->adapter_status); 4119a23fd118Syl 4120a23fd118Syl /* Read the adapter control register for Adapter_enable bit */ 4121a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4122a23fd118Syl &bar0->adapter_control); 4123a23fd118Syl if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 4124a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) && 4125a23fd118Syl (val64 & XGE_HAL_ADAPTER_CNTL_EN)) { 4126a23fd118Syl j++; 4127a23fd118Syl if (j >= hldev->config.link_valid_cnt) { 4128a23fd118Syl if (xge_hal_device_status(hldev, &adp_status) == 4129a23fd118Syl XGE_HAL_OK) { 4130a23fd118Syl if (__hal_verify_pcc_idle(hldev, 4131a23fd118Syl adp_status) != XGE_HAL_OK) { 4132a23fd118Syl return 4133a23fd118Syl XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4134a23fd118Syl } 4135a23fd118Syl xge_debug_device(XGE_TRACE, 41368347601bSyl "adp_status: "XGE_OS_LLXFMT 41378347601bSyl ", link is up on " 4138a23fd118Syl "adapter enable!", 4139a23fd118Syl (unsigned long long)adp_status); 4140a23fd118Syl val64 = xge_os_pio_mem_read64( 4141a23fd118Syl hldev->pdev, 4142a23fd118Syl hldev->regh0, 4143a23fd118Syl &bar0->adapter_control); 4144a23fd118Syl val64 = val64| 4145a23fd118Syl (XGE_HAL_ADAPTER_EOI_TX_ON | 4146a23fd118Syl XGE_HAL_ADAPTER_LED_ON ); 4147a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 4148a23fd118Syl hldev->regh0, val64, 4149a23fd118Syl &bar0->adapter_control); 4150a23fd118Syl xge_os_mdelay(1); 4151a23fd118Syl 4152a23fd118Syl val64 = xge_os_pio_mem_read64( 4153a23fd118Syl hldev->pdev, 4154a23fd118Syl hldev->regh0, 4155a23fd118Syl &bar0->adapter_control); 4156a23fd118Syl break; /* out of for loop */ 4157a23fd118Syl } else { 4158a23fd118Syl return 4159a23fd118Syl XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4160a23fd118Syl } 4161a23fd118Syl } 4162a23fd118Syl } else { 4163a23fd118Syl j = 0; /* Reset the count */ 4164a23fd118Syl /* Turn on the Laser */ 4165a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4166a23fd118Syl &bar0->adapter_control); 4167a23fd118Syl val64 = val64 | XGE_HAL_ADAPTER_EOI_TX_ON; 4168a23fd118Syl xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, 4169a23fd118Syl val64, &bar0->adapter_control); 4170a23fd118Syl 4171a23fd118Syl xge_os_mdelay(1); 4172a23fd118Syl 4173a23fd118Syl /* Now re-enable it as due to noise, hardware 4174a23fd118Syl * turned it off */ 4175a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4176a23fd118Syl &bar0->adapter_control); 4177a23fd118Syl val64 |= XGE_HAL_ADAPTER_CNTL_EN; 4178a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN);/*ECC enable*/ 4179a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4180a23fd118Syl &bar0->adapter_control); 4181a23fd118Syl } 4182a23fd118Syl xge_os_mdelay(1); /* Sleep for 1 msec */ 4183a23fd118Syl i++; 4184a23fd118Syl } while (i < hldev->config.link_retry_cnt); 4185a23fd118Syl 4186a23fd118Syl __hal_device_led_actifity_fix(hldev); 4187a23fd118Syl 4188a23fd118Syl #ifndef XGE_HAL_PROCESS_LINK_INT_IN_ISR 4189a23fd118Syl /* Here we are performing soft reset on XGXS to force link down. 4190a23fd118Syl * Since link is already up, we will get link state change 4191a23fd118Syl * poll notificatoin after adapter is enabled */ 4192a23fd118Syl 41937eced415Sxw __hal_serial_mem_write64(hldev, 0x80010515001E0000ULL, 41947eced415Sxw &bar0->dtx_control); 41957eced415Sxw (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); 4196a23fd118Syl 41977eced415Sxw __hal_serial_mem_write64(hldev, 0x80010515001E00E0ULL, 41987eced415Sxw &bar0->dtx_control); 41997eced415Sxw (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); 4200a23fd118Syl 42017eced415Sxw __hal_serial_mem_write64(hldev, 0x80070515001F00E4ULL, 42027eced415Sxw &bar0->dtx_control); 42037eced415Sxw (void) __hal_serial_mem_read64(hldev, &bar0->dtx_control); 4204a23fd118Syl 4205a23fd118Syl xge_os_mdelay(100); /* Sleep for 500 msec */ 4206a23fd118Syl #else 4207a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 4208a23fd118Syl #endif 4209a23fd118Syl { 4210a23fd118Syl /* 4211a23fd118Syl * With some switches the link state change interrupt does not 4212a23fd118Syl * occur even though the xgxs reset is done as per SPN-006. So, 4213a23fd118Syl * poll the adapter status register and check if the link state 4214a23fd118Syl * is ok. 4215a23fd118Syl */ 4216a23fd118Syl adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4217a23fd118Syl &bar0->adapter_status); 4218a23fd118Syl if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT | 4219a23fd118Syl XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT))) 4220a23fd118Syl { 4221a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 4222a23fd118Syl "enable device causing link state change ind.."); 4223a23fd118Syl (void) __hal_device_handle_link_state_change(hldev); 4224a23fd118Syl } 4225a23fd118Syl } 4226a23fd118Syl 4227a23fd118Syl if (hldev->config.stats_refresh_time_sec != 4228a23fd118Syl XGE_HAL_STATS_REFRESH_DISABLE) 4229a23fd118Syl __hal_stats_enable(&hldev->stats); 4230a23fd118Syl 4231a23fd118Syl return XGE_HAL_OK; 4232a23fd118Syl } 4233a23fd118Syl 4234a23fd118Syl /** 4235a23fd118Syl * xge_hal_device_disable - Disable Xframe adapter. 4236a23fd118Syl * @hldev: Device handle. 4237a23fd118Syl * 4238a23fd118Syl * Disable this device. To gracefully reset the adapter, the host should: 4239a23fd118Syl * 4240a23fd118Syl * - call xge_hal_device_disable(); 4241a23fd118Syl * 4242a23fd118Syl * - call xge_hal_device_intr_disable(); 4243a23fd118Syl * 4244a23fd118Syl * - close all opened channels and clean up outstanding resources; 4245a23fd118Syl * 4246a23fd118Syl * - do some work (error recovery, change mtu, reset, etc); 4247a23fd118Syl * 4248a23fd118Syl * - call xge_hal_device_enable(); 4249a23fd118Syl * 4250a23fd118Syl * - open channels, replenish RxDs, etc. 4251a23fd118Syl * 4252a23fd118Syl * - call xge_hal_device_intr_enable(). 4253a23fd118Syl * 4254a23fd118Syl * Note: Disabling the device does _not_ include disabling of interrupts. 4255a23fd118Syl * After disabling the device stops receiving new frames but those frames 4256a23fd118Syl * that were already in the pipe will keep coming for some few milliseconds. 4257a23fd118Syl * 4258a23fd118Syl * Returns: XGE_HAL_OK - success. 4259a23fd118Syl * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to 4260a23fd118Syl * a "quiescent" state. 4261a23fd118Syl * 4262a23fd118Syl * See also: xge_hal_status_e{}. 4263a23fd118Syl */ 4264a23fd118Syl xge_hal_status_e 4265a23fd118Syl xge_hal_device_disable(xge_hal_device_t *hldev) 4266a23fd118Syl { 4267a23fd118Syl xge_hal_status_e status = XGE_HAL_OK; 4268a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4269a23fd118Syl u64 val64; 4270a23fd118Syl 4271a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "turn off laser, cleanup hardware"); 4272a23fd118Syl 4273a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4274a23fd118Syl &bar0->adapter_control); 4275a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_CNTL_EN); 4276a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4277a23fd118Syl &bar0->adapter_control); 4278a23fd118Syl 4279a23fd118Syl if (__hal_device_wait_quiescent(hldev, &val64) != XGE_HAL_OK) { 4280a23fd118Syl status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4281a23fd118Syl } 4282a23fd118Syl 4283a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1, 4284a23fd118Syl XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT, 4285a23fd118Syl XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4286a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!"); 4287a23fd118Syl status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT; 4288a23fd118Syl } 4289a23fd118Syl 4290a23fd118Syl if (hldev->config.stats_refresh_time_sec != 4291a23fd118Syl XGE_HAL_STATS_REFRESH_DISABLE) 4292a23fd118Syl __hal_stats_disable(&hldev->stats); 4293a23fd118Syl #ifdef XGE_DEBUG_ASSERT 4294a23fd118Syl else 4295a23fd118Syl xge_assert(!hldev->stats.is_enabled); 4296a23fd118Syl #endif 4297a23fd118Syl 42988347601bSyl #ifndef XGE_HAL_DONT_DISABLE_BUS_MASTER_ON_STOP 4299a23fd118Syl __hal_device_bus_master_disable(hldev); 43008347601bSyl #endif 4301a23fd118Syl 4302a23fd118Syl return status; 4303a23fd118Syl } 4304a23fd118Syl 4305a23fd118Syl /** 4306a23fd118Syl * xge_hal_device_reset - Reset device. 4307a23fd118Syl * @hldev: HAL device handle. 4308a23fd118Syl * 4309a23fd118Syl * Soft-reset the device, reset the device stats except reset_cnt. 4310a23fd118Syl * 4311a23fd118Syl * After reset is done, will try to re-initialize HW. 4312a23fd118Syl * 4313a23fd118Syl * Returns: XGE_HAL_OK - success. 4314a23fd118Syl * XGE_HAL_ERR_DEVICE_NOT_INITIALIZED - Device is not initialized. 4315a23fd118Syl * XGE_HAL_ERR_RESET_FAILED - Reset failed. 4316a23fd118Syl * 4317a23fd118Syl * See also: xge_hal_status_e{}. 4318a23fd118Syl */ 4319a23fd118Syl xge_hal_status_e 4320a23fd118Syl xge_hal_device_reset(xge_hal_device_t *hldev) 4321a23fd118Syl { 4322a23fd118Syl xge_hal_status_e status; 4323a23fd118Syl 4324a23fd118Syl /* increment the soft reset counter */ 4325a23fd118Syl u32 reset_cnt = hldev->stats.sw_dev_info_stats.soft_reset_cnt; 4326a23fd118Syl 43278347601bSyl xge_debug_device(XGE_TRACE, "%s (%d)", "resetting the device", reset_cnt); 4328a23fd118Syl 4329a23fd118Syl if (!hldev->is_initialized) 4330a23fd118Syl return XGE_HAL_ERR_DEVICE_NOT_INITIALIZED; 4331a23fd118Syl 4332a23fd118Syl /* actual "soft" reset of the adapter */ 4333a23fd118Syl status = __hal_device_reset(hldev); 4334a23fd118Syl 4335a23fd118Syl /* reset all stats including saved */ 4336a23fd118Syl __hal_stats_soft_reset(hldev, 1); 4337a23fd118Syl 4338a23fd118Syl /* increment reset counter */ 4339a23fd118Syl hldev->stats.sw_dev_info_stats.soft_reset_cnt = reset_cnt + 1; 4340a23fd118Syl 4341a23fd118Syl /* re-initialize rxufca_intr_thres */ 4342a23fd118Syl hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres; 4343a23fd118Syl 4344a23fd118Syl hldev->reset_needed_after_close = 0; 4345a23fd118Syl 4346a23fd118Syl return status; 4347a23fd118Syl } 4348a23fd118Syl 4349a23fd118Syl /** 4350a23fd118Syl * xge_hal_device_status - Check whether Xframe hardware is ready for 4351a23fd118Syl * operation. 4352a23fd118Syl * @hldev: HAL device handle. 4353a23fd118Syl * @hw_status: Xframe status register. Returned by HAL. 4354a23fd118Syl * 4355a23fd118Syl * Check whether Xframe hardware is ready for operation. 4356a23fd118Syl * The checking includes TDMA, RDMA, PFC, PIC, MC_DRAM, and the rest 4357a23fd118Syl * hardware functional blocks. 4358a23fd118Syl * 4359a23fd118Syl * Returns: XGE_HAL_OK if the device is ready for operation. Otherwise 4360a23fd118Syl * returns XGE_HAL_FAIL. Also, fills in adapter status (in @hw_status). 4361a23fd118Syl * 4362a23fd118Syl * See also: xge_hal_status_e{}. 4363a23fd118Syl * Usage: See ex_open{}. 4364a23fd118Syl */ 4365a23fd118Syl xge_hal_status_e 4366a23fd118Syl xge_hal_device_status(xge_hal_device_t *hldev, u64 *hw_status) 4367a23fd118Syl { 4368a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4369a23fd118Syl u64 tmp64; 4370a23fd118Syl 4371a23fd118Syl tmp64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4372a23fd118Syl &bar0->adapter_status); 4373a23fd118Syl 43747eced415Sxw *hw_status = tmp64; 4375a23fd118Syl 4376a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TDMA_READY)) { 4377a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "TDMA is not ready!"); 4378a23fd118Syl return XGE_HAL_FAIL; 4379a23fd118Syl } 4380a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_RDMA_READY)) { 4381a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "RDMA is not ready!"); 4382a23fd118Syl return XGE_HAL_FAIL; 4383a23fd118Syl } 4384a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PFC_READY)) { 4385a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "PFC is not ready!"); 4386a23fd118Syl return XGE_HAL_FAIL; 4387a23fd118Syl } 4388a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY)) { 4389a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "TMAC BUF is not empty!"); 4390a23fd118Syl return XGE_HAL_FAIL; 4391a23fd118Syl } 4392a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT)) { 4393a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "PIC is not QUIESCENT!"); 4394a23fd118Syl return XGE_HAL_FAIL; 4395a23fd118Syl } 4396a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY)) { 4397a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "MC_DRAM is not ready!"); 4398a23fd118Syl return XGE_HAL_FAIL; 4399a23fd118Syl } 4400a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY)) { 4401a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "MC_QUEUES is not ready!"); 4402a23fd118Syl return XGE_HAL_FAIL; 4403a23fd118Syl } 4404a23fd118Syl if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK)) { 4405a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "M_PLL is not locked!"); 4406a23fd118Syl return XGE_HAL_FAIL; 4407a23fd118Syl } 44087eced415Sxw #ifndef XGE_HAL_HERC_EMULATION 44097eced415Sxw /* 44107eced415Sxw * Andrew: in PCI 33 mode, the P_PLL is not used, and therefore, 44117eced415Sxw * the the P_PLL_LOCK bit in the adapter_status register will 44127eced415Sxw * not be asserted. 44137eced415Sxw */ 44147eced415Sxw if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK) && 44157eced415Sxw xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC && 44167eced415Sxw hldev->pci_mode != XGE_HAL_PCI_33MHZ_MODE) { 4417a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "P_PLL is not locked!"); 4418a23fd118Syl return XGE_HAL_FAIL; 4419a23fd118Syl } 44207eced415Sxw #endif 4421a23fd118Syl 4422a23fd118Syl return XGE_HAL_OK; 4423a23fd118Syl } 4424a23fd118Syl 44257eced415Sxw void 44267eced415Sxw __hal_device_msi_intr_endis(xge_hal_device_t *hldev, int flag) 44277eced415Sxw { 44287eced415Sxw u16 msi_control_reg; 44297eced415Sxw 44307eced415Sxw xge_os_pci_read16(hldev->pdev, hldev->cfgh, 44317eced415Sxw xge_offsetof(xge_hal_pci_config_le_t, 44327eced415Sxw msi_control), &msi_control_reg); 44337eced415Sxw 44347eced415Sxw if (flag) 44357eced415Sxw msi_control_reg |= 0x1; 44367eced415Sxw else 44377eced415Sxw msi_control_reg &= ~0x1; 44387eced415Sxw 44397eced415Sxw xge_os_pci_write16(hldev->pdev, hldev->cfgh, 44407eced415Sxw xge_offsetof(xge_hal_pci_config_le_t, 44417eced415Sxw msi_control), msi_control_reg); 44427eced415Sxw } 44437eced415Sxw 44447eced415Sxw void 44457eced415Sxw __hal_device_msix_intr_endis(xge_hal_device_t *hldev, 44467eced415Sxw xge_hal_channel_t *channel, int flag) 44477eced415Sxw { 44487eced415Sxw u64 val64; 44497eced415Sxw xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 44507eced415Sxw 44517eced415Sxw val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 44527eced415Sxw &bar0->xmsi_mask_reg); 44537eced415Sxw 44547eced415Sxw if (flag) 44557eced415Sxw val64 &= ~(1LL << ( 63 - channel->msix_idx )); 44567eced415Sxw else 44577eced415Sxw val64 |= (1LL << ( 63 - channel->msix_idx )); 44587eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 44597eced415Sxw &bar0->xmsi_mask_reg); 44607eced415Sxw } 4461a23fd118Syl 4462a23fd118Syl /** 4463a23fd118Syl * xge_hal_device_intr_enable - Enable Xframe interrupts. 4464a23fd118Syl * @hldev: HAL device handle. 4465a23fd118Syl * @op: One of the xge_hal_device_intr_e enumerated values specifying 4466a23fd118Syl * the type(s) of interrupts to enable. 4467a23fd118Syl * 4468a23fd118Syl * Enable Xframe interrupts. The function is to be executed the last in 4469a23fd118Syl * Xframe initialization sequence. 4470a23fd118Syl * 4471a23fd118Syl * See also: xge_hal_device_intr_disable() 4472a23fd118Syl */ 4473a23fd118Syl void 4474a23fd118Syl xge_hal_device_intr_enable(xge_hal_device_t *hldev) 4475a23fd118Syl { 4476a23fd118Syl xge_list_t *item; 4477a23fd118Syl u64 val64; 4478a23fd118Syl 4479a23fd118Syl /* PRC initialization and configuration */ 4480a23fd118Syl xge_list_for_each(item, &hldev->ring_channels) { 4481a23fd118Syl xge_hal_channel_h channel; 4482a23fd118Syl channel = xge_container_of(item, xge_hal_channel_t, item); 4483a23fd118Syl __hal_ring_prc_enable(channel); 4484a23fd118Syl } 4485a23fd118Syl 4486a23fd118Syl /* enable traffic only interrupts */ 44878347601bSyl if (hldev->config.intr_mode != XGE_HAL_INTR_MODE_IRQLINE) { 44888347601bSyl /* 44898347601bSyl * make sure all interrupts going to be disabled if MSI 44908347601bSyl * is enabled. 44918347601bSyl */ 44927eced415Sxw #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR 44937eced415Sxw __hal_device_intr_mgmt(hldev, XGE_HAL_TX_PIC_INTR, 1); 44947eced415Sxw #else 44958347601bSyl __hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0); 44967eced415Sxw #endif 44978347601bSyl } else { 44988347601bSyl /* 44998347601bSyl * Enable the Tx traffic interrupts only if the TTI feature is 45008347601bSyl * enabled. 45018347601bSyl */ 45028347601bSyl val64 = 0; 45038347601bSyl if (hldev->tti_enabled) 45048347601bSyl val64 = XGE_HAL_TX_TRAFFIC_INTR; 4505a23fd118Syl 45068347601bSyl if (!hldev->config.bimodal_interrupts) 45078347601bSyl val64 |= XGE_HAL_RX_TRAFFIC_INTR; 4508a23fd118Syl 45098347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 45108347601bSyl val64 |= XGE_HAL_RX_TRAFFIC_INTR; 45118347601bSyl 45128347601bSyl val64 |=XGE_HAL_TX_PIC_INTR | 45138347601bSyl XGE_HAL_MC_INTR | 45147eced415Sxw XGE_HAL_TX_DMA_INTR | 45158347601bSyl (hldev->config.sched_timer_us != 45168347601bSyl XGE_HAL_SCHED_TIMER_DISABLED ? XGE_HAL_SCHED_INTR : 0); 45178347601bSyl __hal_device_intr_mgmt(hldev, val64, 1); 45188347601bSyl } 45197eced415Sxw 45207eced415Sxw /* 45217eced415Sxw * Enable MSI-X interrupts 45227eced415Sxw */ 45237eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 45247eced415Sxw 45257eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 45267eced415Sxw /* 45277eced415Sxw * To enable MSI-X, MSI also needs to be enabled, 45287eced415Sxw * due to a bug in the herc NIC. 45297eced415Sxw */ 45307eced415Sxw __hal_device_msi_intr_endis(hldev, 1); 45317eced415Sxw } 45327eced415Sxw 45337eced415Sxw 45347eced415Sxw /* Enable the MSI-X interrupt for each configured channel */ 45357eced415Sxw xge_list_for_each(item, &hldev->fifo_channels) { 45367eced415Sxw xge_hal_channel_t *channel; 45377eced415Sxw 45387eced415Sxw channel = xge_container_of(item, 45397eced415Sxw xge_hal_channel_t, item); 45407eced415Sxw 45417eced415Sxw /* 0 vector is reserved for alarms */ 45427eced415Sxw if (!channel->msix_idx) 45437eced415Sxw continue; 45447eced415Sxw 45457eced415Sxw __hal_device_msix_intr_endis(hldev, channel, 1); 45467eced415Sxw } 45477eced415Sxw 45487eced415Sxw xge_list_for_each(item, &hldev->ring_channels) { 45497eced415Sxw xge_hal_channel_t *channel; 45507eced415Sxw 45517eced415Sxw channel = xge_container_of(item, 45527eced415Sxw xge_hal_channel_t, item); 45537eced415Sxw 45547eced415Sxw /* 0 vector is reserved for alarms */ 45557eced415Sxw if (!channel->msix_idx) 45567eced415Sxw continue; 45577eced415Sxw 45587eced415Sxw __hal_device_msix_intr_endis(hldev, channel, 1); 45597eced415Sxw } 45607eced415Sxw } 45617eced415Sxw 4562a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "interrupts are enabled"); 4563a23fd118Syl } 4564a23fd118Syl 4565a23fd118Syl 4566a23fd118Syl /** 4567a23fd118Syl * xge_hal_device_intr_disable - Disable Xframe interrupts. 4568a23fd118Syl * @hldev: HAL device handle. 4569a23fd118Syl * @op: One of the xge_hal_device_intr_e enumerated values specifying 4570a23fd118Syl * the type(s) of interrupts to disable. 4571a23fd118Syl * 4572a23fd118Syl * Disable Xframe interrupts. 4573a23fd118Syl * 4574a23fd118Syl * See also: xge_hal_device_intr_enable() 4575a23fd118Syl */ 4576a23fd118Syl void 4577a23fd118Syl xge_hal_device_intr_disable(xge_hal_device_t *hldev) 4578a23fd118Syl { 4579a23fd118Syl xge_list_t *item; 45807eced415Sxw xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4581a23fd118Syl u64 val64; 4582a23fd118Syl 45837eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) { 45847eced415Sxw 45857eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 45867eced415Sxw /* 45877eced415Sxw * To disable MSI-X, MSI also needs to be disabled, 45887eced415Sxw * due to a bug in the herc NIC. 45897eced415Sxw */ 45907eced415Sxw __hal_device_msi_intr_endis(hldev, 0); 45917eced415Sxw } 45927eced415Sxw 45937eced415Sxw /* Disable the MSI-X interrupt for each configured channel */ 45947eced415Sxw xge_list_for_each(item, &hldev->fifo_channels) { 45957eced415Sxw xge_hal_channel_t *channel; 45967eced415Sxw 45977eced415Sxw channel = xge_container_of(item, 45987eced415Sxw xge_hal_channel_t, item); 45997eced415Sxw 46007eced415Sxw /* 0 vector is reserved for alarms */ 46017eced415Sxw if (!channel->msix_idx) 46027eced415Sxw continue; 46037eced415Sxw 46047eced415Sxw __hal_device_msix_intr_endis(hldev, channel, 0); 46057eced415Sxw 46067eced415Sxw } 46077eced415Sxw 46087eced415Sxw xge_os_pio_mem_write64(hldev->pdev, 46097eced415Sxw hldev->regh0, 0xFFFFFFFFFFFFFFFFULL, 46107eced415Sxw &bar0->tx_traffic_mask); 46117eced415Sxw 46127eced415Sxw xge_list_for_each(item, &hldev->ring_channels) { 46137eced415Sxw xge_hal_channel_t *channel; 46147eced415Sxw 46157eced415Sxw channel = xge_container_of(item, 46167eced415Sxw xge_hal_channel_t, item); 46177eced415Sxw 46187eced415Sxw /* 0 vector is reserved for alarms */ 46197eced415Sxw if (!channel->msix_idx) 46207eced415Sxw continue; 46217eced415Sxw 46227eced415Sxw __hal_device_msix_intr_endis(hldev, channel, 0); 46237eced415Sxw } 46247eced415Sxw 46257eced415Sxw xge_os_pio_mem_write64(hldev->pdev, 46267eced415Sxw hldev->regh0, 0xFFFFFFFFFFFFFFFFULL, 46277eced415Sxw &bar0->rx_traffic_mask); 46287eced415Sxw } 46297eced415Sxw 4630a23fd118Syl /* 4631a23fd118Syl * Disable traffic only interrupts. 4632a23fd118Syl * Tx traffic interrupts are used only if the TTI feature is 4633a23fd118Syl * enabled. 4634a23fd118Syl */ 4635a23fd118Syl val64 = 0; 46368347601bSyl if (hldev->tti_enabled) 4637a23fd118Syl val64 = XGE_HAL_TX_TRAFFIC_INTR; 4638a23fd118Syl 4639a23fd118Syl val64 |= XGE_HAL_RX_TRAFFIC_INTR | 4640a23fd118Syl XGE_HAL_TX_PIC_INTR | 4641a23fd118Syl XGE_HAL_MC_INTR | 4642a23fd118Syl (hldev->config.sched_timer_us != XGE_HAL_SCHED_TIMER_DISABLED ? 4643a23fd118Syl XGE_HAL_SCHED_INTR : 0); 4644a23fd118Syl __hal_device_intr_mgmt(hldev, val64, 0); 4645a23fd118Syl 4646a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4647a23fd118Syl 0xFFFFFFFFFFFFFFFFULL, 4648a23fd118Syl &bar0->general_int_mask); 4649a23fd118Syl 4650a23fd118Syl 4651a23fd118Syl /* disable all configured PRCs */ 4652a23fd118Syl xge_list_for_each(item, &hldev->ring_channels) { 4653a23fd118Syl xge_hal_channel_h channel; 4654a23fd118Syl channel = xge_container_of(item, xge_hal_channel_t, item); 4655a23fd118Syl __hal_ring_prc_disable(channel); 4656a23fd118Syl } 4657a23fd118Syl 4658a23fd118Syl xge_debug_device(XGE_TRACE, "%s", "interrupts are disabled"); 4659a23fd118Syl } 4660a23fd118Syl 4661a23fd118Syl 4662a23fd118Syl /** 4663a23fd118Syl * xge_hal_device_mcast_enable - Enable Xframe multicast addresses. 4664a23fd118Syl * @hldev: HAL device handle. 4665a23fd118Syl * 4666a23fd118Syl * Enable Xframe multicast addresses. 4667a23fd118Syl * Returns: XGE_HAL_OK on success. 4668a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to enable mcast 4669a23fd118Syl * feature within the time(timeout). 4670a23fd118Syl * 4671a23fd118Syl * See also: xge_hal_device_mcast_disable(), xge_hal_status_e{}. 4672a23fd118Syl */ 4673a23fd118Syl xge_hal_status_e 4674a23fd118Syl xge_hal_device_mcast_enable(xge_hal_device_t *hldev) 4675a23fd118Syl { 4676a23fd118Syl u64 val64; 4677a23fd118Syl xge_hal_pci_bar0_t *bar0; 46788347601bSyl int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET; 4679a23fd118Syl 4680a23fd118Syl if (hldev == NULL) 4681a23fd118Syl return XGE_HAL_ERR_INVALID_DEVICE; 4682a23fd118Syl 4683a23fd118Syl if (hldev->mcast_refcnt) 4684a23fd118Syl return XGE_HAL_OK; 4685a23fd118Syl 46868347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 46878347601bSyl mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC; 46888347601bSyl 4689a23fd118Syl hldev->mcast_refcnt = 1; 4690a23fd118Syl 4691a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4692a23fd118Syl 4693a23fd118Syl /* Enable all Multicast addresses */ 4694a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4695a23fd118Syl XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0x010203040506ULL), 4696a23fd118Syl &bar0->rmac_addr_data0_mem); 4697a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4698a23fd118Syl XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0xfeffffffffffULL), 4699a23fd118Syl &bar0->rmac_addr_data1_mem); 4700a23fd118Syl val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE | 4701a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 47028347601bSyl XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset); 4703a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4704a23fd118Syl &bar0->rmac_addr_cmd_mem); 4705a23fd118Syl 4706a23fd118Syl if (__hal_device_register_poll(hldev, 4707a23fd118Syl &bar0->rmac_addr_cmd_mem, 0, 4708a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4709a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4710a23fd118Syl /* upper layer may require to repeat */ 4711a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4712a23fd118Syl } 4713a23fd118Syl 4714a23fd118Syl return XGE_HAL_OK; 4715a23fd118Syl } 4716a23fd118Syl 4717a23fd118Syl /** 4718a23fd118Syl * xge_hal_device_mcast_disable - Disable Xframe multicast addresses. 4719a23fd118Syl * @hldev: HAL device handle. 4720a23fd118Syl * 4721a23fd118Syl * Disable Xframe multicast addresses. 4722a23fd118Syl * Returns: XGE_HAL_OK - success. 4723a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to disable mcast 4724a23fd118Syl * feature within the time(timeout). 4725a23fd118Syl * 4726a23fd118Syl * See also: xge_hal_device_mcast_enable(), xge_hal_status_e{}. 4727a23fd118Syl */ 4728a23fd118Syl xge_hal_status_e 4729a23fd118Syl xge_hal_device_mcast_disable(xge_hal_device_t *hldev) 4730a23fd118Syl { 4731a23fd118Syl u64 val64; 4732a23fd118Syl xge_hal_pci_bar0_t *bar0; 47338347601bSyl int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET; 4734a23fd118Syl 4735a23fd118Syl if (hldev == NULL) 4736a23fd118Syl return XGE_HAL_ERR_INVALID_DEVICE; 4737a23fd118Syl 4738a23fd118Syl if (hldev->mcast_refcnt == 0) 4739a23fd118Syl return XGE_HAL_OK; 4740a23fd118Syl 47418347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 47428347601bSyl mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC; 47438347601bSyl 4744a23fd118Syl hldev->mcast_refcnt = 0; 4745a23fd118Syl 4746a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4747a23fd118Syl 4748a23fd118Syl /* Disable all Multicast addresses */ 4749a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4750a23fd118Syl XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0xffffffffffffULL), 4751a23fd118Syl &bar0->rmac_addr_data0_mem); 4752a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4753a23fd118Syl XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0), 4754a23fd118Syl &bar0->rmac_addr_data1_mem); 4755a23fd118Syl 4756a23fd118Syl val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE | 4757a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 47588347601bSyl XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset); 4759a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4760a23fd118Syl &bar0->rmac_addr_cmd_mem); 4761a23fd118Syl 4762a23fd118Syl if (__hal_device_register_poll(hldev, 4763a23fd118Syl &bar0->rmac_addr_cmd_mem, 0, 4764a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4765a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4766a23fd118Syl /* upper layer may require to repeat */ 4767a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4768a23fd118Syl } 4769a23fd118Syl 4770a23fd118Syl return XGE_HAL_OK; 4771a23fd118Syl } 4772a23fd118Syl 4773a23fd118Syl /** 4774a23fd118Syl * xge_hal_device_promisc_enable - Enable promiscuous mode. 4775a23fd118Syl * @hldev: HAL device handle. 4776a23fd118Syl * 4777a23fd118Syl * Enable promiscuous mode of Xframe operation. 4778a23fd118Syl * 4779a23fd118Syl * See also: xge_hal_device_promisc_disable(). 4780a23fd118Syl */ 4781a23fd118Syl void 4782a23fd118Syl xge_hal_device_promisc_enable(xge_hal_device_t *hldev) 4783a23fd118Syl { 4784a23fd118Syl u64 val64; 4785a23fd118Syl xge_hal_pci_bar0_t *bar0; 4786a23fd118Syl 4787a23fd118Syl xge_assert(hldev); 4788a23fd118Syl 4789a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4790a23fd118Syl 4791a23fd118Syl if (!hldev->is_promisc) { 4792a23fd118Syl /* Put the NIC into promiscuous mode */ 4793a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4794a23fd118Syl &bar0->mac_cfg); 4795a23fd118Syl val64 |= XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE; 4796a23fd118Syl 4797a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4798a23fd118Syl XGE_HAL_RMAC_CFG_KEY(0x4C0D), 4799a23fd118Syl &bar0->rmac_cfg_key); 4800a23fd118Syl 4801a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 4802a23fd118Syl (u32)(val64 >> 32), 4803a23fd118Syl &bar0->mac_cfg); 4804a23fd118Syl 4805a23fd118Syl hldev->is_promisc = 1; 4806a23fd118Syl xge_debug_device(XGE_TRACE, 48078347601bSyl "mac_cfg 0x"XGE_OS_LLXFMT": promisc enabled", 4808a23fd118Syl (unsigned long long)val64); 4809a23fd118Syl } 4810a23fd118Syl } 4811a23fd118Syl 4812a23fd118Syl /** 4813a23fd118Syl * xge_hal_device_promisc_disable - Disable promiscuous mode. 4814a23fd118Syl * @hldev: HAL device handle. 4815a23fd118Syl * 4816a23fd118Syl * Disable promiscuous mode of Xframe operation. 4817a23fd118Syl * 4818a23fd118Syl * See also: xge_hal_device_promisc_enable(). 4819a23fd118Syl */ 4820a23fd118Syl void 4821a23fd118Syl xge_hal_device_promisc_disable(xge_hal_device_t *hldev) 4822a23fd118Syl { 4823a23fd118Syl u64 val64; 4824a23fd118Syl xge_hal_pci_bar0_t *bar0; 4825a23fd118Syl 4826a23fd118Syl xge_assert(hldev); 4827a23fd118Syl 4828a23fd118Syl bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4829a23fd118Syl 4830a23fd118Syl if (hldev->is_promisc) { 4831a23fd118Syl /* Remove the NIC from promiscuous mode */ 4832a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4833a23fd118Syl &bar0->mac_cfg); 4834a23fd118Syl val64 &= ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE; 4835a23fd118Syl 4836a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4837a23fd118Syl XGE_HAL_RMAC_CFG_KEY(0x4C0D), 4838a23fd118Syl &bar0->rmac_cfg_key); 4839a23fd118Syl 4840a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 4841a23fd118Syl (u32)(val64 >> 32), 4842a23fd118Syl &bar0->mac_cfg); 4843a23fd118Syl 4844a23fd118Syl hldev->is_promisc = 0; 4845a23fd118Syl xge_debug_device(XGE_TRACE, 48468347601bSyl "mac_cfg 0x"XGE_OS_LLXFMT": promisc disabled", 4847a23fd118Syl (unsigned long long)val64); 4848a23fd118Syl } 4849a23fd118Syl } 4850a23fd118Syl 4851a23fd118Syl /** 4852a23fd118Syl * xge_hal_device_macaddr_get - Get MAC addresses. 4853a23fd118Syl * @hldev: HAL device handle. 4854a23fd118Syl * @index: MAC address index, in the range from 0 to 4855a23fd118Syl * XGE_HAL_MAX_MAC_ADDRESSES. 4856a23fd118Syl * @macaddr: MAC address. Returned by HAL. 4857a23fd118Syl * 4858a23fd118Syl * Retrieve one of the stored MAC addresses by reading non-volatile 4859a23fd118Syl * memory on the chip. 4860a23fd118Syl * 4861a23fd118Syl * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported. 4862a23fd118Syl * 4863a23fd118Syl * Returns: XGE_HAL_OK - success. 4864a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac 4865a23fd118Syl * address within the time(timeout). 4866a23fd118Syl * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. 4867a23fd118Syl * 4868a23fd118Syl * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}. 4869a23fd118Syl */ 4870a23fd118Syl xge_hal_status_e 4871a23fd118Syl xge_hal_device_macaddr_get(xge_hal_device_t *hldev, int index, 4872a23fd118Syl macaddr_t *macaddr) 4873a23fd118Syl { 48747eced415Sxw xge_hal_pci_bar0_t *bar0; 4875a23fd118Syl u64 val64; 4876a23fd118Syl int i; 4877a23fd118Syl 4878a23fd118Syl if (hldev == NULL) { 4879a23fd118Syl return XGE_HAL_ERR_INVALID_DEVICE; 4880a23fd118Syl } 4881a23fd118Syl 48827eced415Sxw bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 48837eced415Sxw 4884a23fd118Syl if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) { 4885a23fd118Syl return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 4886a23fd118Syl } 4887a23fd118Syl 4888a23fd118Syl #ifdef XGE_HAL_HERC_EMULATION 4889a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000010000000000, 4890a23fd118Syl &bar0->rmac_addr_data0_mem); 4891a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000000000000000, 4892a23fd118Syl &bar0->rmac_addr_data1_mem); 4893a23fd118Syl val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_RD | 4894a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4895a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)); 4896a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4897a23fd118Syl &bar0->rmac_addr_cmd_mem); 4898a23fd118Syl 4899a23fd118Syl /* poll until done */ 4900a23fd118Syl __hal_device_register_poll(hldev, 4901a23fd118Syl &bar0->rmac_addr_cmd_mem, 0, 4902a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD, 4903a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS); 4904a23fd118Syl 4905a23fd118Syl #endif 4906a23fd118Syl 4907a23fd118Syl val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_RD | 4908a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4909a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) ); 4910a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4911a23fd118Syl &bar0->rmac_addr_cmd_mem); 4912a23fd118Syl 4913a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0, 4914a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4915a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4916a23fd118Syl /* upper layer may require to repeat */ 4917a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4918a23fd118Syl } 4919a23fd118Syl 4920a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 4921a23fd118Syl &bar0->rmac_addr_data0_mem); 4922a23fd118Syl for (i=0; i < XGE_HAL_ETH_ALEN; i++) { 4923a23fd118Syl (*macaddr)[i] = (u8)(val64 >> ((64 - 8) - (i * 8))); 4924a23fd118Syl } 4925a23fd118Syl 4926a23fd118Syl #ifdef XGE_HAL_HERC_EMULATION 4927a23fd118Syl for (i=0; i < XGE_HAL_ETH_ALEN; i++) { 4928a23fd118Syl (*macaddr)[i] = (u8)0; 4929a23fd118Syl } 4930a23fd118Syl (*macaddr)[1] = (u8)1; 4931a23fd118Syl 4932a23fd118Syl #endif 4933a23fd118Syl 4934a23fd118Syl return XGE_HAL_OK; 4935a23fd118Syl } 4936a23fd118Syl 4937a23fd118Syl /** 4938a23fd118Syl * xge_hal_device_macaddr_set - Set MAC address. 4939a23fd118Syl * @hldev: HAL device handle. 4940a23fd118Syl * @index: MAC address index, in the range from 0 to 4941a23fd118Syl * XGE_HAL_MAX_MAC_ADDRESSES. 4942a23fd118Syl * @macaddr: New MAC address to configure. 4943a23fd118Syl * 4944a23fd118Syl * Configure one of the available MAC address "slots". 4945a23fd118Syl * 4946a23fd118Syl * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported. 4947a23fd118Syl * 4948a23fd118Syl * Returns: XGE_HAL_OK - success. 4949a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac 4950a23fd118Syl * address within the time(timeout). 4951a23fd118Syl * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. 4952a23fd118Syl * 4953a23fd118Syl * See also: xge_hal_device_macaddr_get(), xge_hal_status_e{}. 4954a23fd118Syl */ 4955a23fd118Syl xge_hal_status_e 4956a23fd118Syl xge_hal_device_macaddr_set(xge_hal_device_t *hldev, int index, 4957a23fd118Syl macaddr_t macaddr) 4958a23fd118Syl { 4959a23fd118Syl xge_hal_pci_bar0_t *bar0 = 4960a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 4961a23fd118Syl u64 val64, temp64; 4962a23fd118Syl int i; 4963a23fd118Syl 4964a23fd118Syl if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) 4965a23fd118Syl return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 4966a23fd118Syl 4967a23fd118Syl temp64 = 0; 4968a23fd118Syl for (i=0; i < XGE_HAL_ETH_ALEN; i++) { 4969a23fd118Syl temp64 |= macaddr[i]; 4970a23fd118Syl temp64 <<= 8; 4971a23fd118Syl } 4972a23fd118Syl temp64 >>= 8; 4973a23fd118Syl 4974a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4975a23fd118Syl XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(temp64), 4976a23fd118Syl &bar0->rmac_addr_data0_mem); 4977a23fd118Syl 4978a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 4979a23fd118Syl XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0ULL), 4980a23fd118Syl &bar0->rmac_addr_data1_mem); 4981a23fd118Syl 4982a23fd118Syl val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_WE | 4983a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4984a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) ); 4985a23fd118Syl 4986a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 4987a23fd118Syl &bar0->rmac_addr_cmd_mem); 4988a23fd118Syl 4989a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0, 4990a23fd118Syl XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4991a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 4992a23fd118Syl /* upper layer may require to repeat */ 4993a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 4994a23fd118Syl } 4995a23fd118Syl 4996a23fd118Syl return XGE_HAL_OK; 4997a23fd118Syl } 4998a23fd118Syl 49997eced415Sxw /** 50007eced415Sxw * xge_hal_device_macaddr_clear - Set MAC address. 50017eced415Sxw * @hldev: HAL device handle. 50027eced415Sxw * @index: MAC address index, in the range from 0 to 50037eced415Sxw * XGE_HAL_MAX_MAC_ADDRESSES. 50047eced415Sxw * 50057eced415Sxw * Clear one of the available MAC address "slots". 50067eced415Sxw * 50077eced415Sxw * Returns: XGE_HAL_OK - success. 50087eced415Sxw * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac 50097eced415Sxw * address within the time(timeout). 50107eced415Sxw * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index. 50117eced415Sxw * 50127eced415Sxw * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}. 50137eced415Sxw */ 50147eced415Sxw xge_hal_status_e 50157eced415Sxw xge_hal_device_macaddr_clear(xge_hal_device_t *hldev, int index) 50167eced415Sxw { 50177eced415Sxw xge_hal_status_e status; 50187eced415Sxw u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 50197eced415Sxw 50207eced415Sxw status = xge_hal_device_macaddr_set(hldev, index, macaddr); 50217eced415Sxw if (status != XGE_HAL_OK) { 50227eced415Sxw xge_debug_device(XGE_ERR, "%s", 50237eced415Sxw "Not able to set the mac addr"); 50247eced415Sxw return status; 50257eced415Sxw } 50267eced415Sxw 50277eced415Sxw return XGE_HAL_OK; 50287eced415Sxw } 50297eced415Sxw 5030a23fd118Syl /** 5031a23fd118Syl * xge_hal_device_macaddr_find - Finds index in the rmac table. 5032a23fd118Syl * @hldev: HAL device handle. 5033a23fd118Syl * @wanted: Wanted MAC address. 5034a23fd118Syl * 5035a23fd118Syl * See also: xge_hal_device_macaddr_set(). 5036a23fd118Syl */ 5037a23fd118Syl int 5038a23fd118Syl xge_hal_device_macaddr_find(xge_hal_device_t *hldev, macaddr_t wanted) 5039a23fd118Syl { 5040a23fd118Syl int i; 50417eced415Sxw macaddr_t macaddr; 5042a23fd118Syl 5043a23fd118Syl if (hldev == NULL) { 5044a23fd118Syl return XGE_HAL_ERR_INVALID_DEVICE; 5045a23fd118Syl } 5046a23fd118Syl 5047a23fd118Syl for (i=1; i<XGE_HAL_MAX_MAC_ADDRESSES; i++) { 5048a23fd118Syl (void) xge_hal_device_macaddr_get(hldev, i, &macaddr); 5049a23fd118Syl if (!xge_os_memcmp(macaddr, wanted, sizeof(macaddr_t))) { 5050a23fd118Syl return i; 5051a23fd118Syl } 5052a23fd118Syl } 5053a23fd118Syl 5054a23fd118Syl return -1; 5055a23fd118Syl } 5056a23fd118Syl 5057a23fd118Syl /** 5058a23fd118Syl * xge_hal_device_mtu_set - Set MTU. 5059a23fd118Syl * @hldev: HAL device handle. 5060a23fd118Syl * @new_mtu: New MTU size to configure. 5061a23fd118Syl * 5062a23fd118Syl * Set new MTU value. Example, to use jumbo frames: 5063a23fd118Syl * xge_hal_device_mtu_set(my_device, my_channel, 9600); 5064a23fd118Syl * 5065a23fd118Syl * Returns: XGE_HAL_OK on success. 5066a23fd118Syl * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control 5067a23fd118Syl * register. 5068a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to initialize TTI/RTI 5069a23fd118Syl * schemes. 5070a23fd118Syl * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to 5071a23fd118Syl * a "quiescent" state. 5072a23fd118Syl */ 5073a23fd118Syl xge_hal_status_e 5074a23fd118Syl xge_hal_device_mtu_set(xge_hal_device_t *hldev, int new_mtu) 5075a23fd118Syl { 5076a23fd118Syl xge_hal_status_e status; 5077a23fd118Syl 5078a23fd118Syl /* 5079a23fd118Syl * reset needed if 1) new MTU differs, and 5080a23fd118Syl * 2a) device was closed or 5081a23fd118Syl * 2b) device is being upped for first time. 5082a23fd118Syl */ 5083a23fd118Syl if (hldev->config.mtu != new_mtu) { 5084a23fd118Syl if (hldev->reset_needed_after_close || 5085a23fd118Syl !hldev->mtu_first_time_set) { 5086a23fd118Syl status = xge_hal_device_reset(hldev); 5087a23fd118Syl if (status != XGE_HAL_OK) { 5088a23fd118Syl xge_debug_device(XGE_TRACE, "%s", 5089a23fd118Syl "fatal: can not reset the device"); 5090a23fd118Syl return status; 5091a23fd118Syl } 5092a23fd118Syl } 5093a23fd118Syl /* store the new MTU in device, reset will use it */ 5094a23fd118Syl hldev->config.mtu = new_mtu; 5095a23fd118Syl xge_debug_device(XGE_TRACE, "new MTU %d applied", 5096a23fd118Syl new_mtu); 5097a23fd118Syl } 5098a23fd118Syl 5099a23fd118Syl if (!hldev->mtu_first_time_set) 5100a23fd118Syl hldev->mtu_first_time_set = 1; 5101a23fd118Syl 5102a23fd118Syl return XGE_HAL_OK; 5103a23fd118Syl } 5104a23fd118Syl 5105a23fd118Syl /** 5106a23fd118Syl * xge_hal_device_initialize - Initialize Xframe device. 5107a23fd118Syl * @hldev: HAL device handle. 5108a23fd118Syl * @attr: pointer to xge_hal_device_attr_t structure 5109a23fd118Syl * @device_config: Configuration to be _applied_ to the device, 5110a23fd118Syl * For the Xframe configuration "knobs" please 5111a23fd118Syl * refer to xge_hal_device_config_t and Xframe 5112a23fd118Syl * User Guide. 5113a23fd118Syl * 5114a23fd118Syl * Initialize Xframe device. Note that all the arguments of this public API 5115a23fd118Syl * are 'IN', including @hldev. Upper-layer driver (ULD) cooperates with 5116a23fd118Syl * OS to find new Xframe device, locate its PCI and memory spaces. 5117a23fd118Syl * 5118a23fd118Syl * When done, the ULD allocates sizeof(xge_hal_device_t) bytes for HAL 5119a23fd118Syl * to enable the latter to perform Xframe hardware initialization. 5120a23fd118Syl * 5121a23fd118Syl * Returns: XGE_HAL_OK - success. 5122a23fd118Syl * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - Driver is not initialized. 5123a23fd118Syl * XGE_HAL_ERR_BAD_DEVICE_CONFIG - Device configuration params are not 5124a23fd118Syl * valid. 5125a23fd118Syl * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed. 5126a23fd118Syl * XGE_HAL_ERR_BAD_SUBSYSTEM_ID - Device subsystem id is invalid. 5127a23fd118Syl * XGE_HAL_ERR_INVALID_MAC_ADDRESS - Device mac address in not valid. 5128a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac 5129a23fd118Syl * address within the time(timeout) or TTI/RTI initialization failed. 5130a23fd118Syl * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control. 5131a23fd118Syl * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT -Device is not queiscent. 5132a23fd118Syl * 5133a23fd118Syl * See also: xge_hal_device_terminate(), xge_hal_status_e{} 5134a23fd118Syl * xge_hal_device_attr_t{}. 5135a23fd118Syl */ 5136a23fd118Syl xge_hal_status_e 5137a23fd118Syl xge_hal_device_initialize(xge_hal_device_t *hldev, xge_hal_device_attr_t *attr, 5138a23fd118Syl xge_hal_device_config_t *device_config) 5139a23fd118Syl { 5140a23fd118Syl int i; 5141a23fd118Syl xge_hal_status_e status; 5142a23fd118Syl xge_hal_channel_t *channel; 5143a23fd118Syl u16 subsys_device; 5144a23fd118Syl u16 subsys_vendor; 5145a23fd118Syl int total_dram_size, ring_auto_dram_cfg, left_dram_size; 5146a23fd118Syl int total_dram_size_max = 0; 5147a23fd118Syl 51488347601bSyl xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is initializing", 5149a23fd118Syl (unsigned long long)(ulong_t)hldev); 5150a23fd118Syl 5151a23fd118Syl /* sanity check */ 5152a23fd118Syl if (g_xge_hal_driver == NULL || 5153a23fd118Syl !g_xge_hal_driver->is_initialized) { 5154a23fd118Syl return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED; 5155a23fd118Syl } 5156a23fd118Syl 5157a23fd118Syl xge_os_memzero(hldev, sizeof(xge_hal_device_t)); 5158a23fd118Syl 5159a23fd118Syl /* 5160a23fd118Syl * validate a common part of Xframe-I/II configuration 5161a23fd118Syl * (and run check_card() later, once PCI inited - see below) 5162a23fd118Syl */ 5163a23fd118Syl status = __hal_device_config_check_common(device_config); 5164a23fd118Syl if (status != XGE_HAL_OK) 5165a23fd118Syl return status; 5166a23fd118Syl 5167a23fd118Syl /* apply config */ 5168a23fd118Syl xge_os_memcpy(&hldev->config, device_config, 5169a23fd118Syl sizeof(xge_hal_device_config_t)); 5170a23fd118Syl 5171a23fd118Syl /* save original attr */ 5172a23fd118Syl xge_os_memcpy(&hldev->orig_attr, attr, 5173a23fd118Syl sizeof(xge_hal_device_attr_t)); 5174a23fd118Syl 5175a23fd118Syl /* initialize rxufca_intr_thres */ 5176a23fd118Syl hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres; 5177a23fd118Syl 5178a23fd118Syl hldev->regh0 = attr->regh0; 5179a23fd118Syl hldev->regh1 = attr->regh1; 5180a23fd118Syl hldev->regh2 = attr->regh2; 5181a23fd118Syl hldev->isrbar0 = hldev->bar0 = attr->bar0; 5182a23fd118Syl hldev->bar1 = attr->bar1; 5183a23fd118Syl hldev->bar2 = attr->bar2; 5184a23fd118Syl hldev->pdev = attr->pdev; 5185a23fd118Syl hldev->irqh = attr->irqh; 5186a23fd118Syl hldev->cfgh = attr->cfgh; 5187a23fd118Syl 51888347601bSyl /* set initial bimodal timer for bimodal adaptive schema */ 51898347601bSyl hldev->bimodal_timer_val_us = hldev->config.bimodal_timer_lo_us; 51908347601bSyl 5191a23fd118Syl hldev->queueh = xge_queue_create(hldev->pdev, hldev->irqh, 5192a23fd118Syl g_xge_hal_driver->config.queue_size_initial, 5193a23fd118Syl g_xge_hal_driver->config.queue_size_max, 5194a23fd118Syl __hal_device_event_queued, hldev); 5195a23fd118Syl if (hldev->queueh == NULL) 5196a23fd118Syl return XGE_HAL_ERR_OUT_OF_MEMORY; 5197a23fd118Syl 5198a23fd118Syl hldev->magic = XGE_HAL_MAGIC; 5199a23fd118Syl 5200a23fd118Syl xge_assert(hldev->regh0); 5201a23fd118Syl xge_assert(hldev->regh1); 5202a23fd118Syl xge_assert(hldev->bar0); 5203a23fd118Syl xge_assert(hldev->bar1); 5204a23fd118Syl xge_assert(hldev->pdev); 5205a23fd118Syl xge_assert(hldev->irqh); 5206a23fd118Syl xge_assert(hldev->cfgh); 5207a23fd118Syl 5208a23fd118Syl /* initialize some PCI/PCI-X fields of this PCI device. */ 5209a23fd118Syl __hal_device_pci_init(hldev); 5210a23fd118Syl 5211a23fd118Syl /* 5212a23fd118Syl * initlialize lists to properly handling a potential 5213a23fd118Syl * terminate request 5214a23fd118Syl */ 5215a23fd118Syl xge_list_init(&hldev->free_channels); 5216a23fd118Syl xge_list_init(&hldev->fifo_channels); 5217a23fd118Syl xge_list_init(&hldev->ring_channels); 5218a23fd118Syl 5219a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) { 5220a23fd118Syl /* fixups for xena */ 5221a23fd118Syl hldev->config.rth_en = 0; 5222a23fd118Syl hldev->config.rth_spdm_en = 0; 5223a23fd118Syl hldev->config.rts_mac_en = 0; 5224a23fd118Syl total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_XENA; 5225a23fd118Syl 5226a23fd118Syl status = __hal_device_config_check_xena(device_config); 5227a23fd118Syl if (status != XGE_HAL_OK) { 5228a23fd118Syl xge_hal_device_terminate(hldev); 5229a23fd118Syl return status; 5230a23fd118Syl } 52318347601bSyl if (hldev->config.bimodal_interrupts == 1) { 52328347601bSyl xge_hal_device_terminate(hldev); 52338347601bSyl return XGE_HAL_BADCFG_BIMODAL_XENA_NOT_ALLOWED; 52348347601bSyl } else if (hldev->config.bimodal_interrupts == 52358347601bSyl XGE_HAL_DEFAULT_USE_HARDCODE) 52368347601bSyl hldev->config.bimodal_interrupts = 0; 5237a23fd118Syl } else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) { 5238a23fd118Syl /* fixups for herc */ 5239a23fd118Syl total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_HERC; 5240a23fd118Syl status = __hal_device_config_check_herc(device_config); 5241a23fd118Syl if (status != XGE_HAL_OK) { 5242a23fd118Syl xge_hal_device_terminate(hldev); 5243a23fd118Syl return status; 5244a23fd118Syl } 52458347601bSyl if (hldev->config.bimodal_interrupts == 52468347601bSyl XGE_HAL_DEFAULT_USE_HARDCODE) 52478347601bSyl hldev->config.bimodal_interrupts = 1; 5248a23fd118Syl } else { 5249a23fd118Syl xge_debug_device(XGE_ERR, 5250a23fd118Syl "detected unknown device_id 0x%x", hldev->device_id); 5251a23fd118Syl xge_hal_device_terminate(hldev); 5252a23fd118Syl return XGE_HAL_ERR_BAD_DEVICE_ID; 5253a23fd118Syl } 5254a23fd118Syl 52558347601bSyl 5256a23fd118Syl /* allocate and initialize FIFO types of channels according to 5257a23fd118Syl * configuration */ 5258a23fd118Syl for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { 5259a23fd118Syl if (!device_config->fifo.queue[i].configured) 5260a23fd118Syl continue; 5261a23fd118Syl 5262a23fd118Syl channel = __hal_channel_allocate(hldev, i, 5263a23fd118Syl XGE_HAL_CHANNEL_TYPE_FIFO); 5264a23fd118Syl if (channel == NULL) { 5265a23fd118Syl xge_debug_device(XGE_ERR, 5266a23fd118Syl "fifo: __hal_channel_allocate failed"); 5267a23fd118Syl xge_hal_device_terminate(hldev); 5268a23fd118Syl return XGE_HAL_ERR_OUT_OF_MEMORY; 5269a23fd118Syl } 5270a23fd118Syl /* add new channel to the device */ 5271a23fd118Syl xge_list_insert(&channel->item, &hldev->free_channels); 5272a23fd118Syl } 5273a23fd118Syl 5274a23fd118Syl /* 5275a23fd118Syl * automatic DRAM adjustment 5276a23fd118Syl */ 5277a23fd118Syl total_dram_size = 0; 5278a23fd118Syl ring_auto_dram_cfg = 0; 5279a23fd118Syl for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 5280a23fd118Syl if (!device_config->ring.queue[i].configured) 5281a23fd118Syl continue; 5282a23fd118Syl if (device_config->ring.queue[i].dram_size_mb == 5283a23fd118Syl XGE_HAL_DEFAULT_USE_HARDCODE) { 5284a23fd118Syl ring_auto_dram_cfg++; 5285a23fd118Syl continue; 5286a23fd118Syl } 5287a23fd118Syl total_dram_size += device_config->ring.queue[i].dram_size_mb; 5288a23fd118Syl } 5289a23fd118Syl left_dram_size = total_dram_size_max - total_dram_size; 5290a23fd118Syl if (left_dram_size < 0 || 5291a23fd118Syl (ring_auto_dram_cfg && left_dram_size / ring_auto_dram_cfg == 0)) { 5292a23fd118Syl xge_debug_device(XGE_ERR, 5293a23fd118Syl "ring config: exceeded DRAM size %d MB", 5294a23fd118Syl total_dram_size_max); 5295a23fd118Syl xge_hal_device_terminate(hldev); 5296a23fd118Syl return XGE_HAL_BADCFG_RING_QUEUE_SIZE; 5297a23fd118Syl } 5298a23fd118Syl 5299a23fd118Syl /* 5300a23fd118Syl * allocate and initialize RING types of channels according to 5301a23fd118Syl * configuration 5302a23fd118Syl */ 5303a23fd118Syl for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 5304a23fd118Syl if (!device_config->ring.queue[i].configured) 5305a23fd118Syl continue; 5306a23fd118Syl 5307a23fd118Syl if (device_config->ring.queue[i].dram_size_mb == 5308a23fd118Syl XGE_HAL_DEFAULT_USE_HARDCODE) { 5309a23fd118Syl hldev->config.ring.queue[i].dram_size_mb = 5310a23fd118Syl device_config->ring.queue[i].dram_size_mb = 5311a23fd118Syl left_dram_size / ring_auto_dram_cfg; 5312a23fd118Syl } 5313a23fd118Syl 5314a23fd118Syl channel = __hal_channel_allocate(hldev, i, 53157eced415Sxw XGE_HAL_CHANNEL_TYPE_RING); 5316a23fd118Syl if (channel == NULL) { 5317a23fd118Syl xge_debug_device(XGE_ERR, 5318a23fd118Syl "ring: __hal_channel_allocate failed"); 5319a23fd118Syl xge_hal_device_terminate(hldev); 5320a23fd118Syl return XGE_HAL_ERR_OUT_OF_MEMORY; 5321a23fd118Syl } 5322a23fd118Syl /* add new channel to the device */ 5323a23fd118Syl xge_list_insert(&channel->item, &hldev->free_channels); 5324a23fd118Syl } 5325a23fd118Syl 5326a23fd118Syl /* get subsystem IDs */ 5327a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 5328a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), 5329a23fd118Syl &subsys_device); 5330a23fd118Syl xge_os_pci_read16(hldev->pdev, hldev->cfgh, 5331a23fd118Syl xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id), 5332a23fd118Syl &subsys_vendor); 5333a23fd118Syl xge_debug_device(XGE_TRACE, 5334a23fd118Syl "subsystem_id %04x:%04x", 5335a23fd118Syl subsys_vendor, subsys_device); 5336a23fd118Syl 5337a23fd118Syl /* reset device initially */ 5338a23fd118Syl (void) __hal_device_reset(hldev); 5339a23fd118Syl 5340a23fd118Syl /* set host endian before, to assure proper action */ 5341a23fd118Syl status = __hal_device_set_swapper(hldev); 5342a23fd118Syl if (status != XGE_HAL_OK) { 5343a23fd118Syl xge_debug_device(XGE_ERR, 5344a23fd118Syl "__hal_device_set_swapper failed"); 5345a23fd118Syl xge_hal_device_terminate(hldev); 5346a23fd118Syl (void) __hal_device_reset(hldev); 5347a23fd118Syl return status; 5348a23fd118Syl } 5349a23fd118Syl 5350a23fd118Syl #ifndef XGE_HAL_HERC_EMULATION 5351a23fd118Syl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) 5352a23fd118Syl __hal_device_xena_fix_mac(hldev); 5353a23fd118Syl #endif 5354a23fd118Syl 5355a23fd118Syl /* MAC address initialization. 5356a23fd118Syl * For now only one mac address will be read and used. */ 5357a23fd118Syl status = xge_hal_device_macaddr_get(hldev, 0, &hldev->macaddr[0]); 5358a23fd118Syl if (status != XGE_HAL_OK) { 5359a23fd118Syl xge_debug_device(XGE_ERR, 5360a23fd118Syl "xge_hal_device_macaddr_get failed"); 5361a23fd118Syl xge_hal_device_terminate(hldev); 5362a23fd118Syl return status; 5363a23fd118Syl } 5364a23fd118Syl 5365a23fd118Syl if (hldev->macaddr[0][0] == 0xFF && 5366a23fd118Syl hldev->macaddr[0][1] == 0xFF && 5367a23fd118Syl hldev->macaddr[0][2] == 0xFF && 5368a23fd118Syl hldev->macaddr[0][3] == 0xFF && 5369a23fd118Syl hldev->macaddr[0][4] == 0xFF && 5370a23fd118Syl hldev->macaddr[0][5] == 0xFF) { 5371a23fd118Syl xge_debug_device(XGE_ERR, 5372a23fd118Syl "xge_hal_device_macaddr_get returns all FFs"); 5373a23fd118Syl xge_hal_device_terminate(hldev); 5374a23fd118Syl return XGE_HAL_ERR_INVALID_MAC_ADDRESS; 5375a23fd118Syl } 5376a23fd118Syl 5377a23fd118Syl xge_debug_device(XGE_TRACE, 5378a23fd118Syl "default macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x", 5379a23fd118Syl hldev->macaddr[0][0], hldev->macaddr[0][1], 5380a23fd118Syl hldev->macaddr[0][2], hldev->macaddr[0][3], 5381a23fd118Syl hldev->macaddr[0][4], hldev->macaddr[0][5]); 5382a23fd118Syl 5383a23fd118Syl status = __hal_stats_initialize(&hldev->stats, hldev); 5384a23fd118Syl if (status != XGE_HAL_OK) { 5385a23fd118Syl xge_debug_device(XGE_ERR, 5386a23fd118Syl "__hal_stats_initialize failed"); 5387a23fd118Syl xge_hal_device_terminate(hldev); 5388a23fd118Syl return status; 5389a23fd118Syl } 5390a23fd118Syl 5391a23fd118Syl status = __hal_device_hw_initialize(hldev); 5392a23fd118Syl if (status != XGE_HAL_OK) { 5393a23fd118Syl xge_debug_device(XGE_ERR, 5394a23fd118Syl "__hal_device_hw_initialize failed"); 5395a23fd118Syl xge_hal_device_terminate(hldev); 5396a23fd118Syl return status; 5397a23fd118Syl } 53988347601bSyl hldev->dump_buf=(char*)xge_os_malloc(hldev->pdev, XGE_HAL_DUMP_BUF_SIZE); 5399a23fd118Syl if (hldev->dump_buf == NULL) { 5400a23fd118Syl xge_debug_device(XGE_ERR, 5401a23fd118Syl "__hal_device_hw_initialize failed"); 5402a23fd118Syl xge_hal_device_terminate(hldev); 5403a23fd118Syl return XGE_HAL_ERR_OUT_OF_MEMORY; 5404a23fd118Syl } 5405a23fd118Syl 5406a23fd118Syl 5407a23fd118Syl /* Xena-only: need to serialize fifo posts across all device fifos */ 5408a23fd118Syl #if defined(XGE_HAL_TX_MULTI_POST) 5409a23fd118Syl xge_os_spin_lock_init(&hldev->xena_post_lock, hldev->pdev); 5410a23fd118Syl #elif defined(XGE_HAL_TX_MULTI_POST_IRQ) 5411a23fd118Syl xge_os_spin_lock_init_irq(&hldev->xena_post_lock, hldev->irqh); 5412a23fd118Syl #endif 54137eced415Sxw /* Getting VPD data */ 54147eced415Sxw __hal_device_get_vpd_data(hldev); 54157eced415Sxw 5416a23fd118Syl hldev->is_initialized = 1; 5417a23fd118Syl 5418a23fd118Syl return XGE_HAL_OK; 5419a23fd118Syl } 5420a23fd118Syl 5421a23fd118Syl /** 5422a23fd118Syl * xge_hal_device_terminating - Mark the device as 'terminating'. 5423a23fd118Syl * @devh: HAL device handle. 5424a23fd118Syl * 5425a23fd118Syl * Mark the device as 'terminating', going to terminate. Can be used 5426a23fd118Syl * to serialize termination with other running processes/contexts. 5427a23fd118Syl * 5428a23fd118Syl * See also: xge_hal_device_terminate(). 5429a23fd118Syl */ 5430a23fd118Syl void 5431a23fd118Syl xge_hal_device_terminating(xge_hal_device_h devh) 5432a23fd118Syl { 5433a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 54347eced415Sxw xge_list_t *item; 54357eced415Sxw xge_hal_channel_t *channel; 54367eced415Sxw #if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) 54377eced415Sxw unsigned long flags = 0; 54387eced415Sxw #endif 54397eced415Sxw 54407eced415Sxw /* 54417eced415Sxw * go through each opened tx channel and aquire 54427eced415Sxw * lock, so it will serialize with HAL termination flag 54437eced415Sxw */ 54447eced415Sxw xge_list_for_each(item, &hldev->fifo_channels) { 54457eced415Sxw channel = xge_container_of(item, xge_hal_channel_t, item); 54467eced415Sxw #if defined(XGE_HAL_TX_MULTI_RESERVE) 54477eced415Sxw xge_os_spin_lock(&channel->reserve_lock); 54487eced415Sxw #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) 54497eced415Sxw xge_os_spin_lock_irq(&channel->reserve_lock, flags); 54507eced415Sxw #endif 54517eced415Sxw 54527eced415Sxw channel->terminating = 1; 54537eced415Sxw 54547eced415Sxw #if defined(XGE_HAL_TX_MULTI_RESERVE) 54557eced415Sxw xge_os_spin_unlock(&channel->reserve_lock); 54567eced415Sxw #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ) 54577eced415Sxw xge_os_spin_unlock_irq(&channel->reserve_lock, flags); 54587eced415Sxw #endif 54597eced415Sxw } 54607eced415Sxw 5461a23fd118Syl hldev->terminating = 1; 5462a23fd118Syl } 5463a23fd118Syl 5464a23fd118Syl /** 5465a23fd118Syl * xge_hal_device_terminate - Terminate Xframe device. 5466a23fd118Syl * @hldev: HAL device handle. 5467a23fd118Syl * 5468a23fd118Syl * Terminate HAL device. 5469a23fd118Syl * 5470a23fd118Syl * See also: xge_hal_device_initialize(). 5471a23fd118Syl */ 5472a23fd118Syl void 5473a23fd118Syl xge_hal_device_terminate(xge_hal_device_t *hldev) 5474a23fd118Syl { 5475a23fd118Syl xge_assert(g_xge_hal_driver != NULL); 5476a23fd118Syl xge_assert(hldev != NULL); 5477a23fd118Syl xge_assert(hldev->magic == XGE_HAL_MAGIC); 5478a23fd118Syl 5479a23fd118Syl xge_queue_flush(hldev->queueh); 5480a23fd118Syl 5481a23fd118Syl hldev->terminating = 1; 5482a23fd118Syl hldev->is_initialized = 0; 5483a23fd118Syl hldev->in_poll = 0; 5484a23fd118Syl hldev->magic = XGE_HAL_DEAD; 5485a23fd118Syl 5486a23fd118Syl #if defined(XGE_HAL_TX_MULTI_POST) 5487a23fd118Syl xge_os_spin_lock_destroy(&hldev->xena_post_lock, hldev->pdev); 5488a23fd118Syl #elif defined(XGE_HAL_TX_MULTI_POST_IRQ) 5489a23fd118Syl xge_os_spin_lock_destroy_irq(&hldev->xena_post_lock, hldev->pdev); 5490a23fd118Syl #endif 5491a23fd118Syl 54928347601bSyl xge_debug_device(XGE_TRACE, "device "XGE_OS_LLXFMT" is terminating", 5493a23fd118Syl (unsigned long long)(ulong_t)hldev); 5494a23fd118Syl 5495a23fd118Syl xge_assert(xge_list_is_empty(&hldev->fifo_channels)); 5496a23fd118Syl xge_assert(xge_list_is_empty(&hldev->ring_channels)); 5497a23fd118Syl 5498a23fd118Syl if (hldev->stats.is_initialized) { 5499a23fd118Syl __hal_stats_terminate(&hldev->stats); 5500a23fd118Syl } 5501a23fd118Syl 5502a23fd118Syl /* close if open and free all channels */ 5503a23fd118Syl while (!xge_list_is_empty(&hldev->free_channels)) { 5504a23fd118Syl xge_hal_channel_t *channel = (xge_hal_channel_t*) 5505a23fd118Syl hldev->free_channels.next; 5506a23fd118Syl 5507a23fd118Syl xge_assert(!channel->is_open); 5508a23fd118Syl xge_list_remove(&channel->item); 5509a23fd118Syl __hal_channel_free(channel); 5510a23fd118Syl } 5511a23fd118Syl 5512a23fd118Syl if (hldev->queueh) { 5513a23fd118Syl xge_queue_destroy(hldev->queueh); 5514a23fd118Syl } 5515a23fd118Syl 5516a23fd118Syl if (hldev->spdm_table) { 5517a23fd118Syl xge_os_free(hldev->pdev, 5518a23fd118Syl hldev->spdm_table[0], 5519a23fd118Syl (sizeof(xge_hal_spdm_entry_t) * 5520a23fd118Syl hldev->spdm_max_entries)); 5521a23fd118Syl xge_os_free(hldev->pdev, 5522a23fd118Syl hldev->spdm_table, 5523a23fd118Syl (sizeof(xge_hal_spdm_entry_t *) * 5524a23fd118Syl hldev->spdm_max_entries)); 5525a23fd118Syl xge_os_spin_lock_destroy(&hldev->spdm_lock, hldev->pdev); 5526a23fd118Syl hldev->spdm_table = NULL; 5527a23fd118Syl } 5528a23fd118Syl 5529a23fd118Syl if (hldev->dump_buf) { 5530a23fd118Syl xge_os_free(hldev->pdev, hldev->dump_buf, 5531a23fd118Syl XGE_HAL_DUMP_BUF_SIZE); 5532a23fd118Syl hldev->dump_buf = NULL; 5533a23fd118Syl } 55348347601bSyl 55357eced415Sxw if (hldev->device_id != 0) { 55367eced415Sxw int j, pcisize; 55377eced415Sxw 55387eced415Sxw pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)? 55397eced415Sxw XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA; 55407eced415Sxw for (j = 0; j < pcisize; j++) { 55417eced415Sxw xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4, 55427eced415Sxw *((u32*)&hldev->pci_config_space_bios + j)); 55437eced415Sxw } 55447eced415Sxw } 5545a23fd118Syl } 55467eced415Sxw /** 55477eced415Sxw * __hal_device_get_vpd_data - Getting vpd_data. 55487eced415Sxw * 55497eced415Sxw * @hldev: HAL device handle. 55507eced415Sxw * 55517eced415Sxw * Getting product name and serial number from vpd capabilites structure 55527eced415Sxw * 55537eced415Sxw */ 55547eced415Sxw void 55557eced415Sxw __hal_device_get_vpd_data(xge_hal_device_t *hldev) 55567eced415Sxw { 55577eced415Sxw u8 * vpd_data; 55587eced415Sxw u8 data; 55597eced415Sxw int index = 0, count, fail = 0; 55607eced415Sxw u8 vpd_addr = XGE_HAL_CARD_XENA_VPD_ADDR; 55617eced415Sxw if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 55627eced415Sxw vpd_addr = XGE_HAL_CARD_HERC_VPD_ADDR; 55637eced415Sxw 55647eced415Sxw xge_os_strlcpy((char *) hldev->vpd_data.product_name, 55657eced415Sxw "10 Gigabit Ethernet Adapter", 55667eced415Sxw sizeof(hldev->vpd_data.product_name)); 55677eced415Sxw 55687eced415Sxw xge_os_strlcpy((char *) hldev->vpd_data.serial_num, 55697eced415Sxw "not available", 55707eced415Sxw sizeof(hldev->vpd_data.serial_num)); 55717eced415Sxw 55727eced415Sxw vpd_data = ( u8*) xge_os_malloc(hldev->pdev, XGE_HAL_VPD_BUFFER_SIZE + 16); 55737eced415Sxw if ( vpd_data == 0 ) 55747eced415Sxw return; 55757eced415Sxw 55767eced415Sxw for (index = 0; index < XGE_HAL_VPD_BUFFER_SIZE; index +=4 ) { 55777eced415Sxw xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 2), (u8)index); 55787eced415Sxw xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 2), &data); 55797eced415Sxw xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 3), 0); 55807eced415Sxw for (count = 0; count < 5; count++ ) { 55817eced415Sxw xge_os_mdelay(2); 55827eced415Sxw xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 3), &data); 55837eced415Sxw if (data == XGE_HAL_VPD_READ_COMPLETE) 55847eced415Sxw break; 55857eced415Sxw } 55867eced415Sxw 55877eced415Sxw if (count >= 5) { 55887eced415Sxw xge_os_printf("ERR, Reading VPD data failed"); 55897eced415Sxw fail = 1; 55907eced415Sxw break; 55917eced415Sxw } 5592a23fd118Syl 55937eced415Sxw xge_os_pci_read32(hldev->pdev, hldev->cfgh,(vpd_addr + 4), 55947eced415Sxw (u32 *)&vpd_data[index]); 55957eced415Sxw } 55967eced415Sxw 55977eced415Sxw if(!fail) { 55987eced415Sxw 55997eced415Sxw /* read serial number of adapter */ 56007eced415Sxw for (count = 0; count < XGE_HAL_VPD_BUFFER_SIZE; count++) { 56017eced415Sxw if ((vpd_data[count] == 'S') && 56027eced415Sxw (vpd_data[count + 1] == 'N') && 56037eced415Sxw (vpd_data[count + 2] < XGE_HAL_VPD_LENGTH)) { 56047eced415Sxw (void) memset(hldev->vpd_data.serial_num, 0, XGE_HAL_VPD_LENGTH); 56057eced415Sxw (void) memcpy(hldev->vpd_data.serial_num, &vpd_data[count + 3], 56067eced415Sxw vpd_data[count + 2]); 56077eced415Sxw break; 56087eced415Sxw } 56097eced415Sxw } 56107eced415Sxw 56117eced415Sxw if (vpd_data[1] < XGE_HAL_VPD_LENGTH) { 56127eced415Sxw (void) memset(hldev->vpd_data.product_name, 0, vpd_data[1]); 56137eced415Sxw (void) memcpy(hldev->vpd_data.product_name, &vpd_data[3], vpd_data[1]); 56147eced415Sxw } 56157eced415Sxw 56167eced415Sxw } 56177eced415Sxw 56187eced415Sxw xge_os_free(hldev->pdev, vpd_data, XGE_HAL_VPD_BUFFER_SIZE + 16); 56197eced415Sxw } 56207eced415Sxw 56217eced415Sxw 5622a23fd118Syl /** 5623a23fd118Syl * xge_hal_device_handle_tcode - Handle transfer code. 5624a23fd118Syl * @channelh: Channel handle. 5625a23fd118Syl * @dtrh: Descriptor handle. 5626a23fd118Syl * @t_code: One of the enumerated (and documented in the Xframe user guide) 5627a23fd118Syl * "transfer codes". 5628a23fd118Syl * 5629a23fd118Syl * Handle descriptor's transfer code. The latter comes with each completed 5630a23fd118Syl * descriptor, see xge_hal_fifo_dtr_next_completed() and 5631a23fd118Syl * xge_hal_ring_dtr_next_completed(). 5632a23fd118Syl * Transfer codes are enumerated in xgehal-fifo.h and xgehal-ring.h. 5633a23fd118Syl * 5634a23fd118Syl * Returns: one of the xge_hal_status_e{} enumerated types. 5635a23fd118Syl * XGE_HAL_OK - for success. 5636a23fd118Syl * XGE_HAL_ERR_CRITICAL - when encounters critical error. 5637a23fd118Syl */ 5638a23fd118Syl xge_hal_status_e 5639a23fd118Syl xge_hal_device_handle_tcode (xge_hal_channel_h channelh, 5640a23fd118Syl xge_hal_dtr_h dtrh, u8 t_code) 5641a23fd118Syl { 5642a23fd118Syl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 5643a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh; 5644a23fd118Syl 5645a23fd118Syl if (t_code > 15) { 5646a23fd118Syl xge_os_printf("invalid t_code %d", t_code); 5647a23fd118Syl return XGE_HAL_OK; 5648a23fd118Syl } 5649a23fd118Syl 5650a23fd118Syl if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 5651a23fd118Syl hldev->stats.sw_dev_err_stats.txd_t_code_err_cnt[t_code]++; 5652a23fd118Syl 5653a23fd118Syl #if defined(XGE_HAL_DEBUG_BAD_TCODE) 5654a23fd118Syl xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh; 56558347601bSyl xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":" 56568347601bSyl XGE_OS_LLXFMT":"XGE_OS_LLXFMT, 56578347601bSyl txdp->control_1, txdp->control_2, txdp->buffer_pointer, 56588347601bSyl txdp->host_control); 5659a23fd118Syl #endif 5660a23fd118Syl 5661a23fd118Syl /* handle link "down" immediately without going through 5662a23fd118Syl * xge_hal_device_poll() routine. */ 5663a23fd118Syl if (t_code == XGE_HAL_TXD_T_CODE_LOSS_OF_LINK) { 5664a23fd118Syl /* link is down */ 5665a23fd118Syl if (hldev->link_state != XGE_HAL_LINK_DOWN) { 5666a23fd118Syl xge_hal_pci_bar0_t *bar0 = 5667a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 5668a23fd118Syl u64 val64; 5669a23fd118Syl 5670a23fd118Syl hldev->link_state = XGE_HAL_LINK_DOWN; 5671a23fd118Syl 5672a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, 5673a23fd118Syl hldev->regh0, &bar0->adapter_control); 5674a23fd118Syl 5675a23fd118Syl /* turn off LED */ 5676a23fd118Syl val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON); 5677a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 5678a23fd118Syl hldev->regh0, val64, 5679a23fd118Syl &bar0->adapter_control); 5680a23fd118Syl 5681a23fd118Syl g_xge_hal_driver->uld_callbacks.link_down( 5682a23fd118Syl hldev->upper_layer_info); 5683a23fd118Syl } 5684a23fd118Syl } else if (t_code == XGE_HAL_TXD_T_CODE_ABORT_BUFFER || 5685a23fd118Syl t_code == XGE_HAL_TXD_T_CODE_ABORT_DTOR) { 5686a23fd118Syl __hal_device_handle_targetabort(hldev); 5687a23fd118Syl return XGE_HAL_ERR_CRITICAL; 5688a23fd118Syl } 56897eced415Sxw return XGE_HAL_ERR_PKT_DROP; 5690a23fd118Syl } else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 5691a23fd118Syl hldev->stats.sw_dev_err_stats.rxd_t_code_err_cnt[t_code]++; 5692a23fd118Syl 5693a23fd118Syl #if defined(XGE_HAL_DEBUG_BAD_TCODE) 5694a23fd118Syl xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh; 56958347601bSyl xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT 56968347601bSyl ":"XGE_OS_LLXFMT, rxdp->control_1, 56978347601bSyl rxdp->control_2, rxdp->buffer0_ptr, 56988347601bSyl rxdp->host_control); 5699a23fd118Syl #endif 5700a23fd118Syl if (t_code == XGE_HAL_RXD_T_CODE_BAD_ECC) { 5701a23fd118Syl hldev->stats.sw_dev_err_stats.ecc_err_cnt++; 5702a23fd118Syl __hal_device_handle_eccerr(hldev, "rxd_t_code", 5703a23fd118Syl (u64)t_code); 5704a23fd118Syl return XGE_HAL_ERR_CRITICAL; 5705a23fd118Syl } else if (t_code == XGE_HAL_RXD_T_CODE_PARITY || 5706a23fd118Syl t_code == XGE_HAL_RXD_T_CODE_PARITY_ABORT) { 5707a23fd118Syl hldev->stats.sw_dev_err_stats.parity_err_cnt++; 5708a23fd118Syl __hal_device_handle_parityerr(hldev, "rxd_t_code", 5709a23fd118Syl (u64)t_code); 5710a23fd118Syl return XGE_HAL_ERR_CRITICAL; 57117eced415Sxw /* do not drop if detected unknown IPv6 extension */ 57127eced415Sxw } else if (t_code != XGE_HAL_RXD_T_CODE_UNKNOWN_PROTO) { 57137eced415Sxw return XGE_HAL_ERR_PKT_DROP; 5714a23fd118Syl } 5715a23fd118Syl } 5716a23fd118Syl return XGE_HAL_OK; 5717a23fd118Syl } 5718a23fd118Syl 5719a23fd118Syl /** 5720a23fd118Syl * xge_hal_device_link_state - Get link state. 5721a23fd118Syl * @devh: HAL device handle. 5722a23fd118Syl * @ls: Link state, see xge_hal_device_link_state_e{}. 5723a23fd118Syl * 5724a23fd118Syl * Get link state. 5725a23fd118Syl * Returns: XGE_HAL_OK. 5726a23fd118Syl * See also: xge_hal_device_link_state_e{}. 5727a23fd118Syl */ 5728a23fd118Syl xge_hal_status_e xge_hal_device_link_state(xge_hal_device_h devh, 5729a23fd118Syl xge_hal_device_link_state_e *ls) 5730a23fd118Syl { 5731a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5732a23fd118Syl 5733a23fd118Syl xge_assert(ls != NULL); 5734a23fd118Syl *ls = hldev->link_state; 5735a23fd118Syl return XGE_HAL_OK; 5736a23fd118Syl } 5737a23fd118Syl 5738a23fd118Syl /** 5739a23fd118Syl * xge_hal_device_sched_timer - Configure scheduled device interrupt. 5740a23fd118Syl * @devh: HAL device handle. 5741a23fd118Syl * @interval_us: Time interval, in miscoseconds. 5742a23fd118Syl * Unlike transmit and receive interrupts, 5743a23fd118Syl * the scheduled interrupt is generated independently of 5744a23fd118Syl * traffic, but purely based on time. 5745a23fd118Syl * @one_shot: 1 - generate scheduled interrupt only once. 5746a23fd118Syl * 0 - generate scheduled interrupt periodically at the specified 5747a23fd118Syl * @interval_us interval. 5748a23fd118Syl * 5749a23fd118Syl * (Re-)configure scheduled interrupt. Can be called at runtime to change 5750a23fd118Syl * the setting, generate one-shot interrupts based on the resource and/or 5751a23fd118Syl * traffic conditions, other purposes. 5752a23fd118Syl * See also: xge_hal_device_config_t{}. 5753a23fd118Syl */ 5754a23fd118Syl void xge_hal_device_sched_timer(xge_hal_device_h devh, int interval_us, 5755a23fd118Syl int one_shot) 5756a23fd118Syl { 5757a23fd118Syl u64 val64; 5758a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5759a23fd118Syl xge_hal_pci_bar0_t *bar0 = 5760a23fd118Syl (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 5761a23fd118Syl unsigned int interval = hldev->config.pci_freq_mherz * interval_us; 5762a23fd118Syl 5763a23fd118Syl interval = __hal_fix_time_ival_herc(hldev, interval); 5764a23fd118Syl 5765a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 5766a23fd118Syl &bar0->scheduled_int_ctrl); 5767a23fd118Syl if (interval) { 5768a23fd118Syl val64 &= XGE_HAL_SCHED_INT_PERIOD_MASK; 5769a23fd118Syl val64 |= XGE_HAL_SCHED_INT_PERIOD(interval); 5770a23fd118Syl if (one_shot) { 5771a23fd118Syl val64 |= XGE_HAL_SCHED_INT_CTRL_ONE_SHOT; 5772a23fd118Syl } 5773a23fd118Syl val64 |= XGE_HAL_SCHED_INT_CTRL_TIMER_EN; 5774a23fd118Syl } else { 5775a23fd118Syl val64 &= ~XGE_HAL_SCHED_INT_CTRL_TIMER_EN; 5776a23fd118Syl } 5777a23fd118Syl 5778a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 5779a23fd118Syl val64, &bar0->scheduled_int_ctrl); 5780a23fd118Syl 57818347601bSyl xge_debug_device(XGE_TRACE, "sched_timer 0x"XGE_OS_LLXFMT": %s", 5782a23fd118Syl (unsigned long long)val64, 5783a23fd118Syl interval ? "enabled" : "disabled"); 5784a23fd118Syl } 5785a23fd118Syl 5786a23fd118Syl /** 5787a23fd118Syl * xge_hal_device_check_id - Verify device ID. 5788a23fd118Syl * @devh: HAL device handle. 5789a23fd118Syl * 5790a23fd118Syl * Verify device ID. 5791a23fd118Syl * Returns: one of the xge_hal_card_e{} enumerated types. 5792a23fd118Syl * See also: xge_hal_card_e{}. 5793a23fd118Syl */ 5794a23fd118Syl xge_hal_card_e 5795a23fd118Syl xge_hal_device_check_id(xge_hal_device_h devh) 5796a23fd118Syl { 5797a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5798a23fd118Syl switch (hldev->device_id) { 5799a23fd118Syl case XGE_PCI_DEVICE_ID_XENA_1: 5800a23fd118Syl case XGE_PCI_DEVICE_ID_XENA_2: 5801a23fd118Syl return XGE_HAL_CARD_XENA; 5802a23fd118Syl case XGE_PCI_DEVICE_ID_HERC_1: 5803a23fd118Syl case XGE_PCI_DEVICE_ID_HERC_2: 5804a23fd118Syl return XGE_HAL_CARD_HERC; 58057eced415Sxw case XGE_PCI_DEVICE_ID_TITAN_1: 58067eced415Sxw case XGE_PCI_DEVICE_ID_TITAN_2: 58077eced415Sxw return XGE_HAL_CARD_TITAN; 5808a23fd118Syl default: 5809a23fd118Syl return XGE_HAL_CARD_UNKNOWN; 5810a23fd118Syl } 5811a23fd118Syl } 5812a23fd118Syl 5813a23fd118Syl /** 5814a23fd118Syl * xge_hal_device_pci_info_get - Get PCI bus informations such as width, 5815a23fd118Syl * frequency, and mode from previously stored values. 5816a23fd118Syl * @devh: HAL device handle. 5817a23fd118Syl * @pci_mode: pointer to a variable of enumerated type 5818a23fd118Syl * xge_hal_pci_mode_e{}. 5819a23fd118Syl * @bus_frequency: pointer to a variable of enumerated type 5820a23fd118Syl * xge_hal_pci_bus_frequency_e{}. 5821a23fd118Syl * @bus_width: pointer to a variable of enumerated type 5822a23fd118Syl * xge_hal_pci_bus_width_e{}. 5823a23fd118Syl * 5824a23fd118Syl * Get pci mode, frequency, and PCI bus width. 5825a23fd118Syl * Returns: one of the xge_hal_status_e{} enumerated types. 5826a23fd118Syl * XGE_HAL_OK - for success. 5827a23fd118Syl * XGE_HAL_ERR_INVALID_DEVICE - for invalid device handle. 5828a23fd118Syl * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e. 5829a23fd118Syl */ 5830a23fd118Syl xge_hal_status_e 5831a23fd118Syl xge_hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode, 5832a23fd118Syl xge_hal_pci_bus_frequency_e *bus_frequency, 5833a23fd118Syl xge_hal_pci_bus_width_e *bus_width) 5834a23fd118Syl { 5835a23fd118Syl xge_hal_status_e rc_status; 5836a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 5837a23fd118Syl 5838a23fd118Syl if (!hldev || !hldev->is_initialized || hldev->magic != XGE_HAL_MAGIC) { 5839a23fd118Syl rc_status = XGE_HAL_ERR_INVALID_DEVICE; 5840a23fd118Syl xge_debug_device(XGE_ERR, 5841a23fd118Syl "xge_hal_device_pci_info_get error, rc %d for device %p", 5842a23fd118Syl rc_status, hldev); 5843a23fd118Syl 5844a23fd118Syl return rc_status; 5845a23fd118Syl } 5846a23fd118Syl 5847a23fd118Syl *pci_mode = hldev->pci_mode; 5848a23fd118Syl *bus_frequency = hldev->bus_frequency; 5849a23fd118Syl *bus_width = hldev->bus_width; 5850a23fd118Syl rc_status = XGE_HAL_OK; 5851a23fd118Syl return rc_status; 5852a23fd118Syl } 5853a23fd118Syl 5854a23fd118Syl /** 5855a23fd118Syl * xge_hal_reinitialize_hw 5856a23fd118Syl * @hldev: private member of the device structure. 5857a23fd118Syl * 5858a23fd118Syl * This function will soft reset the NIC and re-initalize all the 5859a23fd118Syl * I/O registers to the values they had after it's inital initialization 5860a23fd118Syl * through the probe function. 5861a23fd118Syl */ 5862a23fd118Syl int xge_hal_reinitialize_hw(xge_hal_device_t * hldev) 5863a23fd118Syl { 5864a23fd118Syl (void) xge_hal_device_reset(hldev); 5865a23fd118Syl if (__hal_device_hw_initialize(hldev) != XGE_HAL_OK) { 5866a23fd118Syl xge_hal_device_terminate(hldev); 5867a23fd118Syl (void) __hal_device_reset(hldev); 5868a23fd118Syl return 1; 5869a23fd118Syl } 5870a23fd118Syl return 0; 5871a23fd118Syl } 5872a23fd118Syl 5873a23fd118Syl 5874a23fd118Syl /* 5875a23fd118Syl * __hal_read_spdm_entry_line 5876a23fd118Syl * @hldev: pointer to xge_hal_device_t structure 5877a23fd118Syl * @spdm_line: spdm line in the spdm entry to be read. 5878a23fd118Syl * @spdm_entry: spdm entry of the spdm_line in the SPDM table. 5879a23fd118Syl * @spdm_line_val: Contains the value stored in the spdm line. 5880a23fd118Syl * 5881a23fd118Syl * SPDM table contains upto a maximum of 256 spdm entries. 5882a23fd118Syl * Each spdm entry contains 8 lines and each line stores 8 bytes. 5883a23fd118Syl * This function reads the spdm line(addressed by @spdm_line) 5884a23fd118Syl * of the spdm entry(addressed by @spdm_entry) in 5885a23fd118Syl * the SPDM table. 5886a23fd118Syl */ 5887a23fd118Syl xge_hal_status_e 5888a23fd118Syl __hal_read_spdm_entry_line(xge_hal_device_t *hldev, u8 spdm_line, 5889a23fd118Syl u16 spdm_entry, u64 *spdm_line_val) 5890a23fd118Syl { 5891a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 5892a23fd118Syl u64 val64; 5893a23fd118Syl 5894a23fd118Syl val64 = XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE | 5895a23fd118Syl XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_LINE_SEL(spdm_line) | 5896a23fd118Syl XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_OFFSET(spdm_entry); 5897a23fd118Syl 5898a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 5899a23fd118Syl &bar0->rts_rth_spdm_mem_ctrl); 5900a23fd118Syl 5901a23fd118Syl /* poll until done */ 5902a23fd118Syl if (__hal_device_register_poll(hldev, 5903a23fd118Syl &bar0->rts_rth_spdm_mem_ctrl, 0, 5904a23fd118Syl XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE, 5905a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 5906a23fd118Syl 5907a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 5908a23fd118Syl } 5909a23fd118Syl 5910a23fd118Syl *spdm_line_val = xge_os_pio_mem_read64(hldev->pdev, 5911a23fd118Syl hldev->regh0, &bar0->rts_rth_spdm_mem_data); 5912a23fd118Syl return XGE_HAL_OK; 5913a23fd118Syl } 5914a23fd118Syl 5915a23fd118Syl 5916a23fd118Syl /* 5917a23fd118Syl * __hal_get_free_spdm_entry 5918a23fd118Syl * @hldev: pointer to xge_hal_device_t structure 5919a23fd118Syl * @spdm_entry: Contains an index to the unused spdm entry in the SPDM table. 5920a23fd118Syl * 5921a23fd118Syl * This function returns an index of unused spdm entry in the SPDM 5922a23fd118Syl * table. 5923a23fd118Syl */ 5924a23fd118Syl static xge_hal_status_e 5925a23fd118Syl __hal_get_free_spdm_entry(xge_hal_device_t *hldev, u16 *spdm_entry) 5926a23fd118Syl { 5927a23fd118Syl xge_hal_status_e status; 5928a23fd118Syl u64 spdm_line_val=0; 5929a23fd118Syl 5930a23fd118Syl /* 5931a23fd118Syl * Search in the local SPDM table for a free slot. 5932a23fd118Syl */ 5933a23fd118Syl *spdm_entry = 0; 5934a23fd118Syl for(; *spdm_entry < hldev->spdm_max_entries; (*spdm_entry)++) { 5935a23fd118Syl if (hldev->spdm_table[*spdm_entry]->in_use) { 5936a23fd118Syl break; 5937a23fd118Syl } 5938a23fd118Syl } 5939a23fd118Syl 5940a23fd118Syl if (*spdm_entry >= hldev->spdm_max_entries) { 5941a23fd118Syl return XGE_HAL_ERR_SPDM_TABLE_FULL; 5942a23fd118Syl } 5943a23fd118Syl 5944a23fd118Syl /* 5945a23fd118Syl * Make sure that the corresponding spdm entry in the SPDM 5946a23fd118Syl * table is free. 5947a23fd118Syl * Seventh line of the spdm entry contains information about 5948a23fd118Syl * whether the entry is free or not. 5949a23fd118Syl */ 5950a23fd118Syl if ((status = __hal_read_spdm_entry_line(hldev, 7, *spdm_entry, 5951a23fd118Syl &spdm_line_val)) != XGE_HAL_OK) { 5952a23fd118Syl return status; 5953a23fd118Syl } 5954a23fd118Syl 5955a23fd118Syl /* BIT(63) in spdm_line 7 corresponds to entry_enable bit */ 5956a23fd118Syl if ((spdm_line_val & BIT(63))) { 5957a23fd118Syl /* 5958a23fd118Syl * Log a warning 5959a23fd118Syl */ 5960a23fd118Syl xge_debug_device(XGE_ERR, "Local SPDM table is not " 5961a23fd118Syl "consistent with the actual one for the spdm " 59627eced415Sxw "entry %d", *spdm_entry); 5963a23fd118Syl return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT; 5964a23fd118Syl } 5965a23fd118Syl 5966a23fd118Syl return XGE_HAL_OK; 5967a23fd118Syl } 5968a23fd118Syl 5969a23fd118Syl 59707eced415Sxw /* 59717eced415Sxw * __hal_calc_jhash - Calculate Jenkins hash. 59727eced415Sxw * @msg: Jenkins hash algorithm key. 59737eced415Sxw * @length: Length of the key. 59747eced415Sxw * @golden_ratio: Jenkins hash golden ratio. 59757eced415Sxw * @init_value: Jenkins hash initial value. 59767eced415Sxw * 59777eced415Sxw * This function implements the Jenkins based algorithm used for the 59787eced415Sxw * calculation of the RTH hash. 59797eced415Sxw * Returns: Jenkins hash value. 59807eced415Sxw * 59817eced415Sxw */ 59827eced415Sxw static u32 59837eced415Sxw __hal_calc_jhash(u8 *msg, u32 length, u32 golden_ratio, u32 init_value) 59847eced415Sxw { 59857eced415Sxw 59867eced415Sxw register u32 a,b,c,len; 59877eced415Sxw 59887eced415Sxw /* 59897eced415Sxw * Set up the internal state 59907eced415Sxw */ 59917eced415Sxw len = length; 59927eced415Sxw a = b = golden_ratio; /* the golden ratio; an arbitrary value */ 59937eced415Sxw c = init_value; /* the previous hash value */ 59947eced415Sxw 59957eced415Sxw /* handle most of the key */ 59967eced415Sxw while (len >= 12) 59977eced415Sxw { 59987eced415Sxw a += (msg[0] + ((u32)msg[1]<<8) + ((u32)msg[2]<<16) 59997eced415Sxw + ((u32)msg[3]<<24)); 60007eced415Sxw b += (msg[4] + ((u32)msg[5]<<8) + ((u32)msg[6]<<16) 60017eced415Sxw + ((u32)msg[7]<<24)); 60027eced415Sxw c += (msg[8] + ((u32)msg[9]<<8) + ((u32)msg[10]<<16) 60037eced415Sxw + ((u32)msg[11]<<24)); 60047eced415Sxw mix(a,b,c); 60057eced415Sxw msg += 12; len -= 12; 60067eced415Sxw } 60077eced415Sxw 60087eced415Sxw /* handle the last 11 bytes */ 60097eced415Sxw c += length; 60107eced415Sxw switch(len) /* all the case statements fall through */ 60117eced415Sxw { 60127eced415Sxw case 11: c+= ((u32)msg[10]<<24); 60137eced415Sxw break; 60147eced415Sxw case 10: c+= ((u32)msg[9]<<16); 60157eced415Sxw break; 60167eced415Sxw case 9 : c+= ((u32)msg[8]<<8); 60177eced415Sxw break; 60187eced415Sxw /* the first byte of c is reserved for the length */ 60197eced415Sxw case 8 : b+= ((u32)msg[7]<<24); 60207eced415Sxw break; 60217eced415Sxw case 7 : b+= ((u32)msg[6]<<16); 60227eced415Sxw break; 60237eced415Sxw case 6 : b+= ((u32)msg[5]<<8); 60247eced415Sxw break; 60257eced415Sxw case 5 : b+= msg[4]; 60267eced415Sxw break; 60277eced415Sxw case 4 : a+= ((u32)msg[3]<<24); 60287eced415Sxw break; 60297eced415Sxw case 3 : a+= ((u32)msg[2]<<16); 60307eced415Sxw break; 60317eced415Sxw case 2 : a+= ((u32)msg[1]<<8); 60327eced415Sxw break; 60337eced415Sxw case 1 : a+= msg[0]; 60347eced415Sxw break; 60357eced415Sxw /* case 0: nothing left to add */ 60367eced415Sxw } 60377eced415Sxw 60387eced415Sxw mix(a,b,c); 60397eced415Sxw 60407eced415Sxw /* report the result */ 60417eced415Sxw return c; 60427eced415Sxw } 60437eced415Sxw 6044a23fd118Syl 6045a23fd118Syl /** 6046a23fd118Syl * xge_hal_spdm_entry_add - Add a new entry to the SPDM table. 6047a23fd118Syl * @devh: HAL device handle. 6048a23fd118Syl * @src_ip: Source ip address(IPv4/IPv6). 6049a23fd118Syl * @dst_ip: Destination ip address(IPv4/IPv6). 6050a23fd118Syl * @l4_sp: L4 source port. 6051a23fd118Syl * @l4_dp: L4 destination port. 6052a23fd118Syl * @is_tcp: Set to 1, if the protocol is TCP. 6053a23fd118Syl * 0, if the protocol is UDP. 6054a23fd118Syl * @is_ipv4: Set to 1, if the protocol is IPv4. 6055a23fd118Syl * 0, if the protocol is IPv6. 6056a23fd118Syl * @tgt_queue: Target queue to route the receive packet. 6057a23fd118Syl * 6058a23fd118Syl * This function add a new entry to the SPDM table. 6059a23fd118Syl * 6060a23fd118Syl * Returns: XGE_HAL_OK - success. 6061a23fd118Syl * XGE_HAL_ERR_SPDM_NOT_ENABLED - SPDM support is not enabled. 6062a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to add a new entry with in 6063a23fd118Syl * the time(timeout). 6064a23fd118Syl * XGE_HAL_ERR_SPDM_TABLE_FULL - SPDM table is full. 6065a23fd118Syl * XGE_HAL_ERR_SPDM_INVALID_ENTRY - Invalid SPDM entry. 6066a23fd118Syl * 6067a23fd118Syl * See also: xge_hal_spdm_entry_remove{}. 6068a23fd118Syl */ 6069a23fd118Syl xge_hal_status_e 6070a23fd118Syl xge_hal_spdm_entry_add(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, 6071a23fd118Syl xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, 6072a23fd118Syl u8 is_tcp, u8 is_ipv4, u8 tgt_queue) 6073a23fd118Syl { 6074a23fd118Syl 6075a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 6076a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6077a23fd118Syl u32 jhash_value; 6078a23fd118Syl u32 jhash_init_val; 6079a23fd118Syl u32 jhash_golden_ratio; 6080a23fd118Syl u64 val64; 6081a23fd118Syl int off; 6082a23fd118Syl u16 spdm_entry; 6083a23fd118Syl u8 msg[XGE_HAL_JHASH_MSG_LEN]; 6084a23fd118Syl int ipaddr_len; 6085a23fd118Syl xge_hal_status_e status; 6086a23fd118Syl 6087a23fd118Syl 6088a23fd118Syl if (!hldev->config.rth_spdm_en) { 6089a23fd118Syl return XGE_HAL_ERR_SPDM_NOT_ENABLED; 6090a23fd118Syl } 6091a23fd118Syl 6092a23fd118Syl if ((tgt_queue < XGE_HAL_MIN_RING_NUM) || 6093a23fd118Syl (tgt_queue > XGE_HAL_MAX_RING_NUM)) { 6094a23fd118Syl return XGE_HAL_ERR_SPDM_INVALID_ENTRY; 6095a23fd118Syl } 6096a23fd118Syl 6097a23fd118Syl 6098a23fd118Syl /* 6099a23fd118Syl * Calculate the jenkins hash. 6100a23fd118Syl */ 6101a23fd118Syl /* 6102a23fd118Syl * Create the Jenkins hash algorithm key. 6103a23fd118Syl * key = {L3SA, L3DA, L4SP, L4DP}, if SPDM is configured to 6104a23fd118Syl * use L4 information. Otherwize key = {L3SA, L3DA}. 6105a23fd118Syl */ 6106a23fd118Syl 6107a23fd118Syl if (is_ipv4) { 6108a23fd118Syl ipaddr_len = 4; // In bytes 6109a23fd118Syl } else { 6110a23fd118Syl ipaddr_len = 16; 6111a23fd118Syl } 6112a23fd118Syl 6113a23fd118Syl /* 6114a23fd118Syl * Jenkins hash algorithm expects the key in the big endian 6115a23fd118Syl * format. Since key is the byte array, memcpy won't work in the 6116a23fd118Syl * case of little endian. So, the current code extracts each 6117a23fd118Syl * byte starting from MSB and store it in the key. 6118a23fd118Syl */ 6119a23fd118Syl if (is_ipv4) { 6120a23fd118Syl for (off = 0; off < ipaddr_len; off++) { 6121a23fd118Syl u32 mask = vBIT32(0xff,(off*8),8); 6122a23fd118Syl int shift = 32-(off+1)*8; 6123a23fd118Syl msg[off] = (u8)((src_ip->ipv4.addr & mask) >> shift); 6124a23fd118Syl msg[off+ipaddr_len] = 6125a23fd118Syl (u8)((dst_ip->ipv4.addr & mask) >> shift); 6126a23fd118Syl } 6127a23fd118Syl } else { 6128a23fd118Syl for (off = 0; off < ipaddr_len; off++) { 6129a23fd118Syl int loc = off % 8; 6130a23fd118Syl u64 mask = vBIT(0xff,(loc*8),8); 6131a23fd118Syl int shift = 64-(loc+1)*8; 6132a23fd118Syl 6133a23fd118Syl msg[off] = (u8)((src_ip->ipv6.addr[off/8] & mask) 6134a23fd118Syl >> shift); 6135a23fd118Syl msg[off+ipaddr_len] = (u8)((dst_ip->ipv6.addr[off/8] 6136a23fd118Syl & mask) >> shift); 6137a23fd118Syl } 6138a23fd118Syl } 6139a23fd118Syl 6140a23fd118Syl off = (2*ipaddr_len); 6141a23fd118Syl 6142a23fd118Syl if (hldev->config.rth_spdm_use_l4) { 6143a23fd118Syl msg[off] = (u8)((l4_sp & 0xff00) >> 8); 6144a23fd118Syl msg[off + 1] = (u8)(l4_sp & 0xff); 6145a23fd118Syl msg[off + 2] = (u8)((l4_dp & 0xff00) >> 8); 6146a23fd118Syl msg[off + 3] = (u8)(l4_dp & 0xff); 6147a23fd118Syl off += 4; 6148a23fd118Syl } 6149a23fd118Syl 6150a23fd118Syl /* 6151a23fd118Syl * Calculate jenkins hash for this configuration 6152a23fd118Syl */ 6153a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, 6154a23fd118Syl hldev->regh0, 6155a23fd118Syl &bar0->rts_rth_jhash_cfg); 6156a23fd118Syl jhash_golden_ratio = (u32)(val64 >> 32); 6157a23fd118Syl jhash_init_val = (u32)(val64 & 0xffffffff); 6158a23fd118Syl 6159a23fd118Syl jhash_value = __hal_calc_jhash(msg, off, 6160a23fd118Syl jhash_golden_ratio, 6161a23fd118Syl jhash_init_val); 6162a23fd118Syl 6163a23fd118Syl xge_os_spin_lock(&hldev->spdm_lock); 6164a23fd118Syl 6165a23fd118Syl /* 6166a23fd118Syl * Locate a free slot in the SPDM table. To avoid a seach in the 6167a23fd118Syl * actual SPDM table, which is very expensive in terms of time, 6168a23fd118Syl * we are maintaining a local copy of the table and the search for 6169a23fd118Syl * the free entry is performed in the local table. 6170a23fd118Syl */ 6171a23fd118Syl if ((status = __hal_get_free_spdm_entry(hldev,&spdm_entry)) 6172a23fd118Syl != XGE_HAL_OK) { 6173a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6174a23fd118Syl return status; 6175a23fd118Syl } 6176a23fd118Syl 6177a23fd118Syl /* 6178a23fd118Syl * Add this entry to the SPDM table 6179a23fd118Syl */ 6180a23fd118Syl status = __hal_spdm_entry_add(hldev, src_ip, dst_ip, l4_sp, l4_dp, 6181a23fd118Syl is_tcp, is_ipv4, tgt_queue, 6182a23fd118Syl jhash_value, /* calculated jhash */ 6183a23fd118Syl spdm_entry); 6184a23fd118Syl 6185a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6186a23fd118Syl 6187a23fd118Syl return status; 6188a23fd118Syl } 6189a23fd118Syl 6190a23fd118Syl /** 6191a23fd118Syl * xge_hal_spdm_entry_remove - Remove an entry from the SPDM table. 6192a23fd118Syl * @devh: HAL device handle. 6193a23fd118Syl * @src_ip: Source ip address(IPv4/IPv6). 6194a23fd118Syl * @dst_ip: Destination ip address(IPv4/IPv6). 6195a23fd118Syl * @l4_sp: L4 source port. 6196a23fd118Syl * @l4_dp: L4 destination port. 6197a23fd118Syl * @is_tcp: Set to 1, if the protocol is TCP. 6198a23fd118Syl * 0, if the protocol os UDP. 6199a23fd118Syl * @is_ipv4: Set to 1, if the protocol is IPv4. 6200a23fd118Syl * 0, if the protocol is IPv6. 6201a23fd118Syl * 6202a23fd118Syl * This function remove an entry from the SPDM table. 6203a23fd118Syl * 6204a23fd118Syl * Returns: XGE_HAL_OK - success. 6205a23fd118Syl * XGE_HAL_ERR_SPDM_NOT_ENABLED - SPDM support is not enabled. 6206a23fd118Syl * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to remove an entry with in 6207a23fd118Syl * the time(timeout). 6208a23fd118Syl * XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND - Unable to locate the entry in the SPDM 6209a23fd118Syl * table. 6210a23fd118Syl * 6211a23fd118Syl * See also: xge_hal_spdm_entry_add{}. 6212a23fd118Syl */ 6213a23fd118Syl xge_hal_status_e 6214a23fd118Syl xge_hal_spdm_entry_remove(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip, 6215a23fd118Syl xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, 6216a23fd118Syl u8 is_tcp, u8 is_ipv4) 6217a23fd118Syl { 6218a23fd118Syl 6219a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 6220a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6221a23fd118Syl u64 val64; 6222a23fd118Syl u16 spdm_entry; 6223a23fd118Syl xge_hal_status_e status; 6224a23fd118Syl u64 spdm_line_arr[8]; 6225a23fd118Syl u8 line_no; 6226a23fd118Syl u8 spdm_is_tcp; 6227a23fd118Syl u8 spdm_is_ipv4; 6228a23fd118Syl u16 spdm_l4_sp; 6229a23fd118Syl u16 spdm_l4_dp; 6230a23fd118Syl 6231a23fd118Syl if (!hldev->config.rth_spdm_en) { 6232a23fd118Syl return XGE_HAL_ERR_SPDM_NOT_ENABLED; 6233a23fd118Syl } 6234a23fd118Syl 6235a23fd118Syl xge_os_spin_lock(&hldev->spdm_lock); 6236a23fd118Syl 6237a23fd118Syl /* 6238a23fd118Syl * Poll the rxpic_int_reg register until spdm ready bit is set or 6239a23fd118Syl * timeout happens. 6240a23fd118Syl */ 6241a23fd118Syl if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1, 6242a23fd118Syl XGE_HAL_RX_PIC_INT_REG_SPDM_READY, 6243a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 6244a23fd118Syl 6245a23fd118Syl /* upper layer may require to repeat */ 6246a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6247a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 6248a23fd118Syl } 6249a23fd118Syl 6250a23fd118Syl /* 6251a23fd118Syl * Clear the SPDM READY bit. 6252a23fd118Syl */ 6253a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6254a23fd118Syl &bar0->rxpic_int_reg); 6255a23fd118Syl val64 &= ~XGE_HAL_RX_PIC_INT_REG_SPDM_READY; 6256a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6257a23fd118Syl &bar0->rxpic_int_reg); 6258a23fd118Syl 6259a23fd118Syl /* 6260a23fd118Syl * Search in the local SPDM table to get the index of the 6261a23fd118Syl * corresponding entry in the SPDM table. 6262a23fd118Syl */ 6263a23fd118Syl spdm_entry = 0; 6264a23fd118Syl for (;spdm_entry < hldev->spdm_max_entries; spdm_entry++) { 6265a23fd118Syl if ((!hldev->spdm_table[spdm_entry]->in_use) || 6266a23fd118Syl (hldev->spdm_table[spdm_entry]->is_tcp != is_tcp) || 6267a23fd118Syl (hldev->spdm_table[spdm_entry]->l4_sp != l4_sp) || 6268a23fd118Syl (hldev->spdm_table[spdm_entry]->l4_dp != l4_dp) || 6269a23fd118Syl (hldev->spdm_table[spdm_entry]->is_ipv4 != is_ipv4)) { 6270a23fd118Syl continue; 6271a23fd118Syl } 6272a23fd118Syl 6273a23fd118Syl /* 6274a23fd118Syl * Compare the src/dst IP addresses of source and target 6275a23fd118Syl */ 6276a23fd118Syl if (is_ipv4) { 6277a23fd118Syl if ((hldev->spdm_table[spdm_entry]->src_ip.ipv4.addr 6278a23fd118Syl != src_ip->ipv4.addr) || 6279a23fd118Syl (hldev->spdm_table[spdm_entry]->dst_ip.ipv4.addr 6280a23fd118Syl != dst_ip->ipv4.addr)) { 6281a23fd118Syl continue; 6282a23fd118Syl } 6283a23fd118Syl } else { 6284a23fd118Syl if ((hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[0] 6285a23fd118Syl != src_ip->ipv6.addr[0]) || 6286a23fd118Syl (hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[1] 6287a23fd118Syl != src_ip->ipv6.addr[1]) || 6288a23fd118Syl (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[0] 6289a23fd118Syl != dst_ip->ipv6.addr[0]) || 6290a23fd118Syl (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[1] 6291a23fd118Syl != dst_ip->ipv6.addr[1])) { 6292a23fd118Syl continue; 6293a23fd118Syl } 6294a23fd118Syl } 6295a23fd118Syl break; 6296a23fd118Syl } 6297a23fd118Syl 6298a23fd118Syl if (spdm_entry >= hldev->spdm_max_entries) { 6299a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6300a23fd118Syl return XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND; 6301a23fd118Syl } 6302a23fd118Syl 6303a23fd118Syl /* 6304a23fd118Syl * Retrieve the corresponding entry from the SPDM table and 6305a23fd118Syl * make sure that the data is consistent. 6306a23fd118Syl */ 6307a23fd118Syl for(line_no = 0; line_no < 8; line_no++) { 6308a23fd118Syl 6309a23fd118Syl /* 6310a23fd118Syl * SPDM line 2,3,4 are valid only for IPv6 entry. 6311a23fd118Syl * SPDM line 5 & 6 are reserved. We don't have to 6312a23fd118Syl * read these entries in the above cases. 6313a23fd118Syl */ 6314a23fd118Syl if (((is_ipv4) && 6315a23fd118Syl ((line_no == 2)||(line_no == 3)||(line_no == 4))) || 6316a23fd118Syl (line_no == 5) || 6317a23fd118Syl (line_no == 6)) { 6318a23fd118Syl continue; 6319a23fd118Syl } 6320a23fd118Syl 6321a23fd118Syl if ((status = __hal_read_spdm_entry_line( 6322a23fd118Syl hldev, 6323a23fd118Syl line_no, 6324a23fd118Syl spdm_entry, 6325a23fd118Syl &spdm_line_arr[line_no])) 6326a23fd118Syl != XGE_HAL_OK) { 6327a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6328a23fd118Syl return status; 6329a23fd118Syl } 6330a23fd118Syl } 6331a23fd118Syl 6332a23fd118Syl /* 6333a23fd118Syl * Seventh line of the spdm entry contains the entry_enable 6334a23fd118Syl * bit. Make sure that the entry_enable bit of this spdm entry 6335a23fd118Syl * is set. 6336a23fd118Syl * To remove an entry from the SPDM table, reset this 6337a23fd118Syl * bit. 6338a23fd118Syl */ 6339a23fd118Syl if (!(spdm_line_arr[7] & BIT(63))) { 6340a23fd118Syl /* 6341a23fd118Syl * Log a warning 6342a23fd118Syl */ 6343a23fd118Syl xge_debug_device(XGE_ERR, "Local SPDM table is not " 6344a23fd118Syl "consistent with the actual one for the spdm " 63457eced415Sxw "entry %d ", spdm_entry); 6346a23fd118Syl goto err_exit; 6347a23fd118Syl } 6348a23fd118Syl 6349a23fd118Syl /* 6350a23fd118Syl * Retreive the L4 SP/DP, src/dst ip addresses from the SPDM 6351a23fd118Syl * table and do a comparision. 6352a23fd118Syl */ 6353a23fd118Syl spdm_is_tcp = (u8)((spdm_line_arr[0] & BIT(59)) >> 4); 6354a23fd118Syl spdm_is_ipv4 = (u8)(spdm_line_arr[0] & BIT(63)); 6355a23fd118Syl spdm_l4_sp = (u16)(spdm_line_arr[0] >> 48); 6356a23fd118Syl spdm_l4_dp = (u16)((spdm_line_arr[0] >> 32) & 0xffff); 6357a23fd118Syl 6358a23fd118Syl 6359a23fd118Syl if ((spdm_is_tcp != is_tcp) || 6360a23fd118Syl (spdm_is_ipv4 != is_ipv4) || 6361a23fd118Syl (spdm_l4_sp != l4_sp) || 6362a23fd118Syl (spdm_l4_dp != l4_dp)) { 6363a23fd118Syl /* 6364a23fd118Syl * Log a warning 6365a23fd118Syl */ 6366a23fd118Syl xge_debug_device(XGE_ERR, "Local SPDM table is not " 6367a23fd118Syl "consistent with the actual one for the spdm " 63687eced415Sxw "entry %d ", spdm_entry); 6369a23fd118Syl goto err_exit; 6370a23fd118Syl } 6371a23fd118Syl 6372a23fd118Syl if (is_ipv4) { 6373a23fd118Syl /* Upper 32 bits of spdm_line(64 bit) contains the 6374a23fd118Syl * src IPv4 address. Lower 32 bits of spdm_line 6375a23fd118Syl * contains the destination IPv4 address. 6376a23fd118Syl */ 6377a23fd118Syl u32 temp_src_ip = (u32)(spdm_line_arr[1] >> 32); 6378a23fd118Syl u32 temp_dst_ip = (u32)(spdm_line_arr[1] & 0xffffffff); 6379a23fd118Syl 6380a23fd118Syl if ((temp_src_ip != src_ip->ipv4.addr) || 6381a23fd118Syl (temp_dst_ip != dst_ip->ipv4.addr)) { 6382a23fd118Syl xge_debug_device(XGE_ERR, "Local SPDM table is not " 6383a23fd118Syl "consistent with the actual one for the spdm " 63847eced415Sxw "entry %d ", spdm_entry); 6385a23fd118Syl goto err_exit; 6386a23fd118Syl } 6387a23fd118Syl 6388a23fd118Syl } else { 6389a23fd118Syl /* 6390a23fd118Syl * SPDM line 1 & 2 contains the src IPv6 address. 6391a23fd118Syl * SPDM line 3 & 4 contains the dst IPv6 address. 6392a23fd118Syl */ 6393a23fd118Syl if ((spdm_line_arr[1] != src_ip->ipv6.addr[0]) || 6394a23fd118Syl (spdm_line_arr[2] != src_ip->ipv6.addr[1]) || 6395a23fd118Syl (spdm_line_arr[3] != dst_ip->ipv6.addr[0]) || 6396a23fd118Syl (spdm_line_arr[4] != dst_ip->ipv6.addr[1])) { 6397a23fd118Syl 6398a23fd118Syl /* 6399a23fd118Syl * Log a warning 6400a23fd118Syl */ 6401a23fd118Syl xge_debug_device(XGE_ERR, "Local SPDM table is not " 6402a23fd118Syl "consistent with the actual one for the spdm " 64037eced415Sxw "entry %d ", spdm_entry); 6404a23fd118Syl goto err_exit; 6405a23fd118Syl } 6406a23fd118Syl } 6407a23fd118Syl 6408a23fd118Syl /* 6409a23fd118Syl * Reset the entry_enable bit to zero 6410a23fd118Syl */ 6411a23fd118Syl spdm_line_arr[7] &= ~BIT(63); 6412a23fd118Syl 6413a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6414a23fd118Syl spdm_line_arr[7], 6415a23fd118Syl (void *)((char *)hldev->spdm_mem_base + 6416a23fd118Syl (spdm_entry * 64) + (7 * 8))); 6417a23fd118Syl 6418a23fd118Syl /* 6419a23fd118Syl * Wait for the operation to be completed. 6420a23fd118Syl */ 6421a23fd118Syl if (__hal_device_register_poll(hldev, 6422a23fd118Syl &bar0->rxpic_int_reg, 1, 6423a23fd118Syl XGE_HAL_RX_PIC_INT_REG_SPDM_READY, 6424a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 6425a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6426a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 6427a23fd118Syl } 6428a23fd118Syl 6429a23fd118Syl /* 6430a23fd118Syl * Make the corresponding spdm entry in the local SPDM table 6431a23fd118Syl * available for future use. 6432a23fd118Syl */ 6433a23fd118Syl hldev->spdm_table[spdm_entry]->in_use = 0; 6434a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6435a23fd118Syl 6436a23fd118Syl return XGE_HAL_OK; 6437a23fd118Syl 6438a23fd118Syl err_exit: 6439a23fd118Syl xge_os_spin_unlock(&hldev->spdm_lock); 6440a23fd118Syl return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT; 6441a23fd118Syl } 6442a23fd118Syl 6443a23fd118Syl /* 6444a23fd118Syl * __hal_device_rti_set 6445a23fd118Syl * @ring: The post_qid of the ring. 6446a23fd118Syl * @channel: HAL channel of the ring. 6447a23fd118Syl * 6448a23fd118Syl * This function stores the RTI value associated for the MSI and 6449a23fd118Syl * also unmasks this particular RTI in the rti_mask register. 6450a23fd118Syl */ 6451a23fd118Syl static void __hal_device_rti_set(int ring_qid, xge_hal_channel_t *channel) 6452a23fd118Syl { 6453a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6454a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6455a23fd118Syl u64 val64; 6456a23fd118Syl 64577eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || 64587eced415Sxw hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) 64597eced415Sxw channel->rti = (u8)ring_qid; 64607eced415Sxw 6461a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6462a23fd118Syl &bar0->rx_traffic_mask); 6463a23fd118Syl val64 &= ~BIT(ring_qid); 6464a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 6465a23fd118Syl hldev->regh0, val64, 6466a23fd118Syl &bar0->rx_traffic_mask); 6467a23fd118Syl } 6468a23fd118Syl 6469a23fd118Syl /* 6470a23fd118Syl * __hal_device_tti_set 6471a23fd118Syl * @ring: The post_qid of the FIFO. 6472a23fd118Syl * @channel: HAL channel the FIFO. 6473a23fd118Syl * 6474a23fd118Syl * This function stores the TTI value associated for the MSI and 6475a23fd118Syl * also unmasks this particular TTI in the tti_mask register. 6476a23fd118Syl */ 6477a23fd118Syl static void __hal_device_tti_set(int fifo_qid, xge_hal_channel_t *channel) 6478a23fd118Syl { 6479a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6480a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6481a23fd118Syl u64 val64; 6482a23fd118Syl 64837eced415Sxw if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI || 64847eced415Sxw hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) 64857eced415Sxw channel->tti = (u8)fifo_qid; 64867eced415Sxw 6487a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6488a23fd118Syl &bar0->tx_traffic_mask); 6489a23fd118Syl val64 &= ~BIT(fifo_qid); 6490a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, 6491a23fd118Syl hldev->regh0, val64, 6492a23fd118Syl &bar0->tx_traffic_mask); 6493a23fd118Syl } 6494a23fd118Syl 6495a23fd118Syl /** 6496a23fd118Syl * xge_hal_channel_msi_set - Associate a RTI with a ring or TTI with a 6497a23fd118Syl * FIFO for a given MSI. 6498a23fd118Syl * @channelh: HAL channel handle. 6499a23fd118Syl * @msi: MSI Number associated with the channel. 6500a23fd118Syl * @msi_msg: The MSI message associated with the MSI number above. 6501a23fd118Syl * 6502a23fd118Syl * This API will associate a given channel (either Ring or FIFO) with the 6503a23fd118Syl * given MSI number. It will alo program the Tx_Mat/Rx_Mat tables in the 6504a23fd118Syl * hardware to indicate this association to the hardware. 6505a23fd118Syl */ 6506a23fd118Syl xge_hal_status_e 6507a23fd118Syl xge_hal_channel_msi_set(xge_hal_channel_h channelh, int msi, u32 msi_msg) 6508a23fd118Syl { 6509a23fd118Syl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 6510a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6511a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6512a23fd118Syl u64 val64; 6513a23fd118Syl 6514a23fd118Syl channel->msi_msg = msi_msg; 6515a23fd118Syl if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 6516a23fd118Syl int ring = channel->post_qid; 6517a23fd118Syl xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Ring: %d," 65187eced415Sxw " MSI: %d", channel->msi_msg, ring, msi); 6519a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6520a23fd118Syl &bar0->rx_mat); 6521a23fd118Syl val64 |= XGE_HAL_SET_RX_MAT(ring, msi); 6522a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6523a23fd118Syl &bar0->rx_mat); 6524a23fd118Syl __hal_device_rti_set(ring, channel); 6525a23fd118Syl } else { 6526a23fd118Syl int fifo = channel->post_qid; 6527a23fd118Syl xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Fifo: %d," 65287eced415Sxw " MSI: %d", channel->msi_msg, fifo, msi); 6529a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6530a23fd118Syl &bar0->tx_mat[0]); 6531a23fd118Syl val64 |= XGE_HAL_SET_TX_MAT(fifo, msi); 6532a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6533a23fd118Syl &bar0->tx_mat[0]); 6534a23fd118Syl __hal_device_tti_set(fifo, channel); 6535a23fd118Syl } 6536a23fd118Syl 6537a23fd118Syl return XGE_HAL_OK; 6538a23fd118Syl } 65397eced415Sxw 65407eced415Sxw /** 65417eced415Sxw * xge_hal_mask_msix - Begin IRQ processing. 65427eced415Sxw * @hldev: HAL device handle. 65437eced415Sxw * @msi_id: MSI ID 65447eced415Sxw * 65457eced415Sxw * The function masks the msix interrupt for the given msi_id 65467eced415Sxw * 65477eced415Sxw * Note: 65487eced415Sxw * 65497eced415Sxw * Returns: 0, 65507eced415Sxw * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range 65517eced415Sxw * status. 65527eced415Sxw * See also: 65537eced415Sxw */ 65547eced415Sxw xge_hal_status_e 65557eced415Sxw xge_hal_mask_msix(xge_hal_device_h devh, int msi_id) 65567eced415Sxw { 65577eced415Sxw xge_hal_status_e status = XGE_HAL_OK; 65587eced415Sxw xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 65597eced415Sxw u32 *bar2 = (u32 *)hldev->bar2; 65607eced415Sxw u32 val32; 65617eced415Sxw 65627eced415Sxw xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES); 65637eced415Sxw 65647eced415Sxw val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]); 65657eced415Sxw val32 |= 1; 65667eced415Sxw xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]); 65677eced415Sxw return status; 65687eced415Sxw } 65697eced415Sxw 65707eced415Sxw /** 65717eced415Sxw * xge_hal_mask_msix - Begin IRQ processing. 65727eced415Sxw * @hldev: HAL device handle. 65737eced415Sxw * @msi_id: MSI ID 65747eced415Sxw * 65757eced415Sxw * The function masks the msix interrupt for the given msi_id 65767eced415Sxw * 65777eced415Sxw * Note: 65787eced415Sxw * 65797eced415Sxw * Returns: 0, 65807eced415Sxw * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range 65817eced415Sxw * status. 65827eced415Sxw * See also: 65837eced415Sxw */ 65847eced415Sxw xge_hal_status_e 65857eced415Sxw xge_hal_unmask_msix(xge_hal_device_h devh, int msi_id) 65867eced415Sxw { 65877eced415Sxw xge_hal_status_e status = XGE_HAL_OK; 65887eced415Sxw xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 65897eced415Sxw u32 *bar2 = (u32 *)hldev->bar2; 65907eced415Sxw u32 val32; 65917eced415Sxw 65927eced415Sxw xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES); 65937eced415Sxw 65947eced415Sxw val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]); 65957eced415Sxw val32 &= ~1; 65967eced415Sxw xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]); 65977eced415Sxw return status; 65987eced415Sxw } 65997eced415Sxw 6600a23fd118Syl /* 66017eced415Sxw * __hal_set_msix_vals 6602a23fd118Syl * @devh: HAL device handle. 6603a23fd118Syl * @msix_value: 32bit MSI-X value transferred across PCI to @msix_address. 6604a23fd118Syl * Filled in by this function. 6605a23fd118Syl * @msix_address: 32bit MSI-X DMA address. 6606a23fd118Syl * Filled in by this function. 6607a23fd118Syl * @msix_idx: index that corresponds to the (@msix_value, @msix_address) 6608a23fd118Syl * entry in the table of MSI-X (value, address) pairs. 6609a23fd118Syl * 6610a23fd118Syl * This function will program the hardware associating the given 6611a23fd118Syl * address/value cobination to the specified msi number. 6612a23fd118Syl */ 66137eced415Sxw static void __hal_set_msix_vals (xge_hal_device_h devh, 6614a23fd118Syl u32 *msix_value, 6615a23fd118Syl u64 *msix_addr, 6616a23fd118Syl int msix_idx) 6617a23fd118Syl { 6618a23fd118Syl int cnt = 0; 6619a23fd118Syl 6620a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 6621a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6622a23fd118Syl u64 val64; 6623a23fd118Syl 6624a23fd118Syl val64 = XGE_HAL_XMSI_NO(msix_idx) | XGE_HAL_XMSI_STROBE; 6625a23fd118Syl __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, 6626a23fd118Syl (u32)(val64 >> 32), &bar0->xmsi_access); 6627a23fd118Syl __hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, 6628a23fd118Syl (u32)(val64), &bar0->xmsi_access); 6629a23fd118Syl do { 6630a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6631a23fd118Syl &bar0->xmsi_access); 6632a23fd118Syl if (val64 & XGE_HAL_XMSI_STROBE) 6633a23fd118Syl break; 6634a23fd118Syl cnt++; 6635a23fd118Syl xge_os_mdelay(20); 6636a23fd118Syl } while(cnt < 5); 6637a23fd118Syl *msix_value = (u32)(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6638a23fd118Syl &bar0->xmsi_data)); 6639a23fd118Syl *msix_addr = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6640a23fd118Syl &bar0->xmsi_address); 6641a23fd118Syl } 6642a23fd118Syl 6643a23fd118Syl /** 6644a23fd118Syl * xge_hal_channel_msix_set - Associate MSI-X with a channel. 6645a23fd118Syl * @channelh: HAL channel handle. 6646a23fd118Syl * @msix_idx: index that corresponds to a particular (@msix_value, 6647a23fd118Syl * @msix_address) entry in the MSI-X table. 6648a23fd118Syl * 6649a23fd118Syl * This API associates a given channel (either Ring or FIFO) with the 6650a23fd118Syl * given MSI-X number. It programs the Xframe's Tx_Mat/Rx_Mat tables 6651a23fd118Syl * to indicate this association. 6652a23fd118Syl */ 6653a23fd118Syl xge_hal_status_e 6654a23fd118Syl xge_hal_channel_msix_set(xge_hal_channel_h channelh, int msix_idx) 6655a23fd118Syl { 6656a23fd118Syl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh; 6657a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh; 6658a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 6659a23fd118Syl u64 val64; 6660a23fd118Syl 6661a23fd118Syl if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) { 6662a23fd118Syl /* Currently Ring and RTI is one on one. */ 6663a23fd118Syl int ring = channel->post_qid; 6664a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6665a23fd118Syl &bar0->rx_mat); 6666a23fd118Syl val64 |= XGE_HAL_SET_RX_MAT(ring, msix_idx); 6667a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6668a23fd118Syl &bar0->rx_mat); 6669a23fd118Syl __hal_device_rti_set(ring, channel); 66707eced415Sxw hldev->config.ring.queue[channel->post_qid].intr_vector = 66717eced415Sxw msix_idx; 6672a23fd118Syl } else if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 6673a23fd118Syl int fifo = channel->post_qid; 6674a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6675a23fd118Syl &bar0->tx_mat[0]); 6676a23fd118Syl val64 |= XGE_HAL_SET_TX_MAT(fifo, msix_idx); 6677a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6678a23fd118Syl &bar0->tx_mat[0]); 6679a23fd118Syl __hal_device_tti_set(fifo, channel); 66807eced415Sxw hldev->config.fifo.queue[channel->post_qid].intr_vector = 66817eced415Sxw msix_idx; 6682a23fd118Syl } 6683a23fd118Syl channel->msix_idx = msix_idx; 66847eced415Sxw __hal_set_msix_vals(hldev, &channel->msix_data, 6685a23fd118Syl &channel->msix_address, 6686a23fd118Syl channel->msix_idx); 6687a23fd118Syl 6688a23fd118Syl return XGE_HAL_OK; 6689a23fd118Syl } 6690a23fd118Syl 6691a23fd118Syl #if defined(XGE_HAL_CONFIG_LRO) 6692a23fd118Syl /** 6693a23fd118Syl * xge_hal_lro_terminate - Terminate lro resources. 6694a23fd118Syl * @lro_scale: Amount of lro memory. 6695a23fd118Syl * @hldev: Hal device structure. 6696a23fd118Syl * 6697a23fd118Syl */ 6698a23fd118Syl void 6699a23fd118Syl xge_hal_lro_terminate(u32 lro_scale, 6700a23fd118Syl xge_hal_device_t *hldev) 6701a23fd118Syl { 6702a23fd118Syl } 6703a23fd118Syl 6704a23fd118Syl /** 6705a23fd118Syl * xge_hal_lro_init - Initiate lro resources. 6706a23fd118Syl * @lro_scale: Amount of lro memory. 6707a23fd118Syl * @hldev: Hal device structure. 6708a23fd118Syl * Note: For time being I am using only one LRO per device. Later on size 6709a23fd118Syl * will be increased. 6710a23fd118Syl */ 67117eced415Sxw 6712a23fd118Syl xge_hal_status_e 6713a23fd118Syl xge_hal_lro_init(u32 lro_scale, 6714a23fd118Syl xge_hal_device_t *hldev) 6715a23fd118Syl { 67167eced415Sxw int i; 67178347601bSyl 67188347601bSyl if (hldev->config.lro_sg_size == XGE_HAL_DEFAULT_USE_HARDCODE) 67198347601bSyl hldev->config.lro_sg_size = XGE_HAL_LRO_DEFAULT_SG_SIZE; 67208347601bSyl 67218347601bSyl if (hldev->config.lro_frm_len == XGE_HAL_DEFAULT_USE_HARDCODE) 67228347601bSyl hldev->config.lro_frm_len = XGE_HAL_LRO_DEFAULT_FRM_LEN; 67238347601bSyl 67247eced415Sxw for (i=0; i < XGE_HAL_MAX_RING_NUM; i++) 67257eced415Sxw { 67267eced415Sxw xge_os_memzero(hldev->lro_desc[i].lro_pool, 67277eced415Sxw sizeof(lro_t) * XGE_HAL_LRO_MAX_BUCKETS); 67287eced415Sxw 67297eced415Sxw hldev->lro_desc[i].lro_next_idx = 0; 67307eced415Sxw hldev->lro_desc[i].lro_recent = NULL; 67317eced415Sxw } 6732a23fd118Syl 6733a23fd118Syl return XGE_HAL_OK; 6734a23fd118Syl } 6735a23fd118Syl #endif 6736a23fd118Syl 6737a23fd118Syl 6738a23fd118Syl /** 6739a23fd118Syl * xge_hal_device_poll - HAL device "polling" entry point. 67408347601bSyl * @devh: HAL device. 6741a23fd118Syl * 6742a23fd118Syl * HAL "polling" entry point. Note that this is part of HAL public API. 6743a23fd118Syl * Upper-Layer driver _must_ periodically poll HAL via 6744a23fd118Syl * xge_hal_device_poll(). 6745a23fd118Syl * 6746a23fd118Syl * HAL uses caller's execution context to serially process accumulated 6747a23fd118Syl * slow-path events, such as link state changes and hardware error 6748a23fd118Syl * indications. 6749a23fd118Syl * 6750a23fd118Syl * The rate of polling could be somewhere between 500us to 10ms, 6751a23fd118Syl * depending on requirements (e.g., the requirement to support fail-over 6752a23fd118Syl * could mean that 500us or even 100us polling interval need to be used). 6753a23fd118Syl * 6754a23fd118Syl * The need and motivation for external polling includes 6755a23fd118Syl * 6756a23fd118Syl * - remove the error-checking "burden" from the HAL interrupt handler 6757a23fd118Syl * (see xge_hal_device_handle_irq()); 6758a23fd118Syl * 6759a23fd118Syl * - remove the potential source of portability issues by _not_ 6760a23fd118Syl * implementing separate polling thread within HAL itself. 6761a23fd118Syl * 6762a23fd118Syl * See also: xge_hal_event_e{}, xge_hal_driver_config_t{}. 6763a23fd118Syl * Usage: See ex_slow_path{}. 6764a23fd118Syl */ 6765a23fd118Syl void 6766a23fd118Syl xge_hal_device_poll(xge_hal_device_h devh) 6767a23fd118Syl { 6768a23fd118Syl unsigned char item_buf[sizeof(xge_queue_item_t) + 6769a23fd118Syl XGE_DEFAULT_EVENT_MAX_DATA_SIZE]; 6770a23fd118Syl xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf; 6771a23fd118Syl xge_queue_status_e qstatus; 6772a23fd118Syl xge_hal_status_e hstatus; 6773a23fd118Syl int i = 0; 6774a23fd118Syl int queue_has_critical_event = 0; 6775a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t*)devh; 6776a23fd118Syl 67777eced415Sxw xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) + 67787eced415Sxw XGE_DEFAULT_EVENT_MAX_DATA_SIZE)); 67797eced415Sxw 6780a23fd118Syl _again: 6781a23fd118Syl if (!hldev->is_initialized || 6782a23fd118Syl hldev->terminating || 6783a23fd118Syl hldev->magic != XGE_HAL_MAGIC) 6784a23fd118Syl return; 6785a23fd118Syl 67868347601bSyl if(hldev->stats.sw_dev_err_stats.xpak_counter.tick_period < 72000) 67878347601bSyl { 67888347601bSyl /* 67898347601bSyl * Wait for an Hour 67908347601bSyl */ 67918347601bSyl hldev->stats.sw_dev_err_stats.xpak_counter.tick_period++; 67928347601bSyl } else { 67938347601bSyl /* 67948347601bSyl * Logging Error messages in the excess temperature, 67958347601bSyl * Bias current, laser ouput for three cycle 67968347601bSyl */ 67978347601bSyl __hal_updt_stats_xpak(hldev); 67988347601bSyl hldev->stats.sw_dev_err_stats.xpak_counter.tick_period = 0; 67998347601bSyl } 68008347601bSyl 6801a23fd118Syl if (!queue_has_critical_event) 6802a23fd118Syl queue_has_critical_event = 6803a23fd118Syl __queue_get_reset_critical(hldev->queueh); 6804a23fd118Syl 6805a23fd118Syl hldev->in_poll = 1; 6806a23fd118Syl while (i++ < XGE_HAL_DRIVER_QUEUE_CONSUME_MAX || queue_has_critical_event) { 6807a23fd118Syl 6808a23fd118Syl qstatus = xge_queue_consume(hldev->queueh, 6809a23fd118Syl XGE_DEFAULT_EVENT_MAX_DATA_SIZE, 6810a23fd118Syl item); 6811a23fd118Syl if (qstatus == XGE_QUEUE_IS_EMPTY) 6812a23fd118Syl break; 6813a23fd118Syl 6814a23fd118Syl xge_debug_queue(XGE_TRACE, 68158347601bSyl "queueh 0x"XGE_OS_LLXFMT" consumed event: %d ctxt 0x" 68168347601bSyl XGE_OS_LLXFMT, (u64)(ulong_t)hldev->queueh, item->event_type, 6817a23fd118Syl (u64)(ulong_t)item->context); 6818a23fd118Syl 6819a23fd118Syl if (!hldev->is_initialized || 6820a23fd118Syl hldev->magic != XGE_HAL_MAGIC) { 6821a23fd118Syl hldev->in_poll = 0; 6822a23fd118Syl return; 6823a23fd118Syl } 6824a23fd118Syl 6825a23fd118Syl switch (item->event_type) { 6826a23fd118Syl case XGE_HAL_EVENT_LINK_IS_UP: { 6827a23fd118Syl if (!queue_has_critical_event && 6828a23fd118Syl g_xge_hal_driver->uld_callbacks.link_up) { 6829a23fd118Syl g_xge_hal_driver->uld_callbacks.link_up( 6830a23fd118Syl hldev->upper_layer_info); 6831a23fd118Syl hldev->link_state = XGE_HAL_LINK_UP; 6832a23fd118Syl } 6833a23fd118Syl } break; 6834a23fd118Syl case XGE_HAL_EVENT_LINK_IS_DOWN: { 6835a23fd118Syl if (!queue_has_critical_event && 6836a23fd118Syl g_xge_hal_driver->uld_callbacks.link_down) { 6837a23fd118Syl g_xge_hal_driver->uld_callbacks.link_down( 6838a23fd118Syl hldev->upper_layer_info); 6839a23fd118Syl hldev->link_state = XGE_HAL_LINK_DOWN; 6840a23fd118Syl } 6841a23fd118Syl } break; 6842a23fd118Syl case XGE_HAL_EVENT_SERR: 6843a23fd118Syl case XGE_HAL_EVENT_ECCERR: 6844a23fd118Syl case XGE_HAL_EVENT_PARITYERR: 6845a23fd118Syl case XGE_HAL_EVENT_TARGETABORT: 6846a23fd118Syl case XGE_HAL_EVENT_SLOT_FREEZE: { 6847a23fd118Syl void *item_data = xge_queue_item_data(item); 68488347601bSyl xge_hal_event_e event_type = item->event_type; 6849a23fd118Syl u64 val64 = *((u64*)item_data); 6850a23fd118Syl 6851a23fd118Syl if (event_type != XGE_HAL_EVENT_SLOT_FREEZE) 6852a23fd118Syl if (xge_hal_device_is_slot_freeze(hldev)) 6853a23fd118Syl event_type = XGE_HAL_EVENT_SLOT_FREEZE; 6854a23fd118Syl if (g_xge_hal_driver->uld_callbacks.crit_err) { 6855a23fd118Syl g_xge_hal_driver->uld_callbacks.crit_err( 6856a23fd118Syl hldev->upper_layer_info, 6857a23fd118Syl event_type, 6858a23fd118Syl val64); 6859a23fd118Syl /* handle one critical event per poll cycle */ 6860a23fd118Syl hldev->in_poll = 0; 6861a23fd118Syl return; 6862a23fd118Syl } 6863a23fd118Syl } break; 6864a23fd118Syl default: { 6865a23fd118Syl xge_debug_queue(XGE_TRACE, 6866a23fd118Syl "got non-HAL event %d", 6867a23fd118Syl item->event_type); 6868a23fd118Syl } break; 6869a23fd118Syl } 6870a23fd118Syl 6871a23fd118Syl /* broadcast this event */ 6872a23fd118Syl if (g_xge_hal_driver->uld_callbacks.event) 6873a23fd118Syl g_xge_hal_driver->uld_callbacks.event(item); 6874a23fd118Syl } 6875a23fd118Syl 6876a23fd118Syl if (g_xge_hal_driver->uld_callbacks.before_device_poll) { 6877a23fd118Syl if (g_xge_hal_driver->uld_callbacks.before_device_poll( 6878a23fd118Syl hldev) != 0) { 6879a23fd118Syl hldev->in_poll = 0; 6880a23fd118Syl return; 6881a23fd118Syl } 6882a23fd118Syl } 6883a23fd118Syl 6884a23fd118Syl hstatus = __hal_device_poll(hldev); 6885a23fd118Syl if (g_xge_hal_driver->uld_callbacks.after_device_poll) 6886a23fd118Syl g_xge_hal_driver->uld_callbacks.after_device_poll(hldev); 6887a23fd118Syl 6888a23fd118Syl /* 6889a23fd118Syl * handle critical error right away: 6890a23fd118Syl * - walk the device queue again 6891a23fd118Syl * - drop non-critical events, if any 6892a23fd118Syl * - look for the 1st critical 6893a23fd118Syl */ 6894a23fd118Syl if (hstatus == XGE_HAL_ERR_CRITICAL) { 6895a23fd118Syl queue_has_critical_event = 1; 6896a23fd118Syl goto _again; 6897a23fd118Syl } 6898a23fd118Syl 6899a23fd118Syl hldev->in_poll = 0; 6900a23fd118Syl } 6901a23fd118Syl 6902a23fd118Syl /** 6903a23fd118Syl * xge_hal_rts_rth_init - Set enhanced mode for RTS hashing. 6904a23fd118Syl * @hldev: HAL device handle. 6905a23fd118Syl * 6906a23fd118Syl * This function is used to set the adapter to enhanced mode. 6907a23fd118Syl * 6908a23fd118Syl * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). 6909a23fd118Syl */ 6910a23fd118Syl void 6911a23fd118Syl xge_hal_rts_rth_init(xge_hal_device_t *hldev) 6912a23fd118Syl { 6913a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6914a23fd118Syl u64 val64; 6915a23fd118Syl 6916a23fd118Syl /* 6917a23fd118Syl * Set the receive traffic steering mode from default(classic) 6918a23fd118Syl * to enhanced. 6919a23fd118Syl */ 6920a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6921a23fd118Syl &bar0->rts_ctrl); 6922a23fd118Syl val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE; 6923a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6924a23fd118Syl val64, &bar0->rts_ctrl); 6925a23fd118Syl } 6926a23fd118Syl 6927a23fd118Syl /** 6928a23fd118Syl * xge_hal_rts_rth_clr - Clear RTS hashing. 6929a23fd118Syl * @hldev: HAL device handle. 6930a23fd118Syl * 6931a23fd118Syl * This function is used to clear all RTS hashing related stuff. 6932a23fd118Syl * It brings the adapter out from enhanced mode to classic mode. 6933a23fd118Syl * It also clears RTS_RTH_CFG register i.e clears hash type, function etc. 6934a23fd118Syl * 6935a23fd118Syl * See also: xge_hal_rts_rth_set(), xge_hal_rts_rth_itable_set(). 6936a23fd118Syl */ 6937a23fd118Syl void 6938a23fd118Syl xge_hal_rts_rth_clr(xge_hal_device_t *hldev) 6939a23fd118Syl { 6940a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6941a23fd118Syl u64 val64; 6942a23fd118Syl 6943a23fd118Syl /* 6944a23fd118Syl * Set the receive traffic steering mode from default(classic) 6945a23fd118Syl * to enhanced. 6946a23fd118Syl */ 6947a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 6948a23fd118Syl &bar0->rts_ctrl); 6949a23fd118Syl val64 &= ~XGE_HAL_RTS_CTRL_ENHANCED_MODE; 6950a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 6951a23fd118Syl val64, &bar0->rts_ctrl); 6952a23fd118Syl val64 = 0; 6953a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6954a23fd118Syl &bar0->rts_rth_cfg); 6955a23fd118Syl } 6956a23fd118Syl 6957a23fd118Syl /** 6958a23fd118Syl * xge_hal_rts_rth_set - Set/configure RTS hashing. 6959a23fd118Syl * @hldev: HAL device handle. 6960a23fd118Syl * @def_q: default queue 6961a23fd118Syl * @hash_type: hash type i.e TcpIpV4, TcpIpV6 etc. 6962a23fd118Syl * @bucket_size: no of least significant bits to be used for hashing. 6963a23fd118Syl * 6964a23fd118Syl * Used to set/configure all RTS hashing related stuff. 6965a23fd118Syl * - set the steering mode to enhanced. 6966a23fd118Syl * - set hash function i.e algo selection. 6967a23fd118Syl * - set the default queue. 6968a23fd118Syl * 6969a23fd118Syl * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(). 6970a23fd118Syl */ 6971a23fd118Syl void 6972a23fd118Syl xge_hal_rts_rth_set(xge_hal_device_t *hldev, u8 def_q, u64 hash_type, 6973a23fd118Syl u16 bucket_size) 6974a23fd118Syl { 6975a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 6976a23fd118Syl u64 val64; 6977a23fd118Syl 6978a23fd118Syl val64 = XGE_HAL_RTS_DEFAULT_Q(def_q); 6979a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6980a23fd118Syl &bar0->rts_default_q); 6981a23fd118Syl 6982a23fd118Syl val64 = hash_type; 6983a23fd118Syl val64 |= XGE_HAL_RTS_RTH_EN; 6984a23fd118Syl val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(bucket_size); 6985a23fd118Syl val64 |= XGE_HAL_RTS_RTH_ALG_SEL_MS; 6986a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 6987a23fd118Syl &bar0->rts_rth_cfg); 6988a23fd118Syl } 6989a23fd118Syl 6990a23fd118Syl /** 6991a23fd118Syl * xge_hal_rts_rth_start - Start RTS hashing. 6992a23fd118Syl * @hldev: HAL device handle. 6993a23fd118Syl * 6994a23fd118Syl * Used to Start RTS hashing . 6995a23fd118Syl * 6996a23fd118Syl * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start. 6997a23fd118Syl */ 6998a23fd118Syl void 6999a23fd118Syl xge_hal_rts_rth_start(xge_hal_device_t *hldev) 7000a23fd118Syl { 7001a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7002a23fd118Syl u64 val64; 7003a23fd118Syl 7004a23fd118Syl 7005a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 7006a23fd118Syl &bar0->rts_rth_cfg); 7007a23fd118Syl val64 |= XGE_HAL_RTS_RTH_EN; 7008a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7009a23fd118Syl &bar0->rts_rth_cfg); 7010a23fd118Syl } 7011a23fd118Syl 7012a23fd118Syl /** 7013a23fd118Syl * xge_hal_rts_rth_stop - Stop the RTS hashing. 7014a23fd118Syl * @hldev: HAL device handle. 7015a23fd118Syl * 7016a23fd118Syl * Used to Staop RTS hashing . 7017a23fd118Syl * 7018a23fd118Syl * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start. 7019a23fd118Syl */ 7020a23fd118Syl void 7021a23fd118Syl xge_hal_rts_rth_stop(xge_hal_device_t *hldev) 7022a23fd118Syl { 7023a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7024a23fd118Syl u64 val64; 7025a23fd118Syl 7026a23fd118Syl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 7027a23fd118Syl &bar0->rts_rth_cfg); 7028a23fd118Syl val64 &= ~XGE_HAL_RTS_RTH_EN; 7029a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7030a23fd118Syl &bar0->rts_rth_cfg); 7031a23fd118Syl } 7032a23fd118Syl 7033a23fd118Syl /** 7034a23fd118Syl * xge_hal_rts_rth_itable_set - Set/configure indirection table (IT). 7035a23fd118Syl * @hldev: HAL device handle. 7036a23fd118Syl * @itable: Pointer to the indirection table 7037a23fd118Syl * @itable_size: no of least significant bits to be used for hashing 7038a23fd118Syl * 7039a23fd118Syl * Used to set/configure indirection table. 7040a23fd118Syl * It enables the required no of entries in the IT. 7041a23fd118Syl * It adds entries to the IT. 7042a23fd118Syl * 7043a23fd118Syl * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). 7044a23fd118Syl */ 7045a23fd118Syl xge_hal_status_e 7046a23fd118Syl xge_hal_rts_rth_itable_set(xge_hal_device_t *hldev, u8 *itable, u32 itable_size) 7047a23fd118Syl { 7048a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 7049a23fd118Syl u64 val64; 7050a23fd118Syl u32 idx; 7051a23fd118Syl 7052a23fd118Syl for (idx = 0; idx < itable_size; idx++) { 7053a23fd118Syl val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN | 7054a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_DATA(itable[idx]); 7055a23fd118Syl 7056a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7057a23fd118Syl &bar0->rts_rth_map_mem_data); 7058a23fd118Syl 7059a23fd118Syl /* execute */ 7060a23fd118Syl val64 = (XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE | 7061a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE | 7062a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(idx)); 7063a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7064a23fd118Syl &bar0->rts_rth_map_mem_ctrl); 7065a23fd118Syl 7066a23fd118Syl /* poll until done */ 7067a23fd118Syl if (__hal_device_register_poll(hldev, 7068a23fd118Syl &bar0->rts_rth_map_mem_ctrl, 0, 7069a23fd118Syl XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE, 7070a23fd118Syl XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 7071a23fd118Syl /* upper layer may require to repeat */ 7072a23fd118Syl return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 7073a23fd118Syl } 7074a23fd118Syl } 7075a23fd118Syl 7076a23fd118Syl return XGE_HAL_OK; 7077a23fd118Syl } 7078a23fd118Syl 7079a23fd118Syl 7080a23fd118Syl /** 7081a23fd118Syl * xge_hal_device_rts_rth_key_set - Configure 40byte secret for hash calc. 7082a23fd118Syl * 7083a23fd118Syl * @hldev: HAL device handle. 7084a23fd118Syl * @KeySize: Number of 64-bit words 7085a23fd118Syl * @Key: upto 40-byte array of 8-bit values 7086a23fd118Syl * This function configures the 40-byte secret which is used for hash 7087a23fd118Syl * calculation. 7088a23fd118Syl * 7089a23fd118Syl * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set(). 7090a23fd118Syl */ 7091a23fd118Syl void 7092a23fd118Syl xge_hal_device_rts_rth_key_set(xge_hal_device_t *hldev, u8 KeySize, u8 *Key) 7093a23fd118Syl { 7094a23fd118Syl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *) hldev->bar0; 7095a23fd118Syl u64 val64; 7096a23fd118Syl u32 entry, nreg, i; 7097a23fd118Syl 7098a23fd118Syl entry = 0; 7099a23fd118Syl nreg = 0; 7100a23fd118Syl 7101a23fd118Syl while( KeySize ) { 7102a23fd118Syl val64 = 0; 7103a23fd118Syl for ( i = 0; i < 8 ; i++) { 7104a23fd118Syl /* Prepare 64-bit word for 'nreg' containing 8 keys. */ 7105a23fd118Syl if (i) 7106a23fd118Syl val64 <<= 8; 7107a23fd118Syl val64 |= Key[entry++]; 7108a23fd118Syl } 7109a23fd118Syl 7110a23fd118Syl KeySize--; 7111a23fd118Syl 7112a23fd118Syl /* temp64 = XGE_HAL_RTH_HASH_MASK_n(val64, (n<<3), (n<<3)+7);*/ 7113a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7114a23fd118Syl &bar0->rts_rth_hash_mask[nreg++]); 7115a23fd118Syl } 7116a23fd118Syl 7117a23fd118Syl while( nreg < 5 ) { 7118a23fd118Syl /* Clear the rest if key is less than 40 bytes */ 7119a23fd118Syl val64 = 0; 7120a23fd118Syl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 7121a23fd118Syl &bar0->rts_rth_hash_mask[nreg++]); 7122a23fd118Syl } 7123a23fd118Syl } 7124a23fd118Syl 7125a23fd118Syl 7126a23fd118Syl /** 7127a23fd118Syl * xge_hal_device_is_closed - Device is closed 7128a23fd118Syl * 71298347601bSyl * @devh: HAL device handle. 7130a23fd118Syl */ 7131a23fd118Syl int 7132a23fd118Syl xge_hal_device_is_closed(xge_hal_device_h devh) 7133a23fd118Syl { 7134a23fd118Syl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 7135a23fd118Syl 7136a23fd118Syl if (xge_list_is_empty(&hldev->fifo_channels) && 7137a23fd118Syl xge_list_is_empty(&hldev->ring_channels)) 7138a23fd118Syl return 1; 7139a23fd118Syl 7140a23fd118Syl return 0; 7141a23fd118Syl } 7142a23fd118Syl 71438347601bSyl xge_hal_status_e 71448347601bSyl xge_hal_device_rts_section_enable(xge_hal_device_h devh, int index) 71458347601bSyl { 71468347601bSyl u64 val64; 71478347601bSyl int section; 71488347601bSyl int max_addr = XGE_HAL_MAX_MAC_ADDRESSES; 71498347601bSyl 71508347601bSyl xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 71518347601bSyl xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0; 71528347601bSyl 71538347601bSyl if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) 71548347601bSyl max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC; 71558347601bSyl 71568347601bSyl if ( index >= max_addr ) 71578347601bSyl return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES; 71588347601bSyl 71598347601bSyl /* 71608347601bSyl * Calculate the section value 71618347601bSyl */ 71628347601bSyl section = index / 32; 71638347601bSyl 71647eced415Sxw xge_debug_device(XGE_TRACE, "the Section value is %d ", section); 71658347601bSyl 71668347601bSyl val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, 71678347601bSyl &bar0->rts_mac_cfg); 71688347601bSyl switch(section) 71698347601bSyl { 71708347601bSyl case 0: 71718347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT0_EN; 71728347601bSyl break; 71738347601bSyl case 1: 71748347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT1_EN; 71758347601bSyl break; 71768347601bSyl case 2: 71778347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT2_EN; 71788347601bSyl break; 71798347601bSyl case 3: 71808347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT3_EN; 71818347601bSyl break; 71828347601bSyl case 4: 71838347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT4_EN; 71848347601bSyl break; 71858347601bSyl case 5: 71868347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT5_EN; 71878347601bSyl break; 71888347601bSyl case 6: 71898347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT6_EN; 71908347601bSyl break; 71918347601bSyl case 7: 71928347601bSyl val64 |= XGE_HAL_RTS_MAC_SECT7_EN; 71938347601bSyl break; 71948347601bSyl default: 71957eced415Sxw xge_debug_device(XGE_ERR, "Invalid Section value %d " 71968347601bSyl , section); 71978347601bSyl } 71988347601bSyl 71998347601bSyl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 72008347601bSyl val64, &bar0->rts_mac_cfg); 72018347601bSyl return XGE_HAL_OK; 72028347601bSyl } 72038347601bSyl 72047eced415Sxw /* 72057eced415Sxw * xge_hal_fix_rldram_ecc_error 72067eced415Sxw * @hldev: private member of the device structure. 72077eced415Sxw * 72087eced415Sxw * SXE-02-010. This function will turn OFF the ECC error reporting for the 72097eced415Sxw * interface bet'n external Micron RLDRAM II device and memory controller. 72107eced415Sxw * The error would have been reported in RLD_ECC_DB_ERR_L and RLD_ECC_DB_ERR_U 72117eced415Sxw * fileds of MC_ERR_REG register. Issue reported by HP-Unix folks during the 72127eced415Sxw * qualification of Herc. 72137eced415Sxw */ 72148347601bSyl xge_hal_status_e 72157eced415Sxw xge_hal_fix_rldram_ecc_error(xge_hal_device_t *hldev) 72168347601bSyl { 72177eced415Sxw xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; 72187eced415Sxw u64 val64; 72198347601bSyl 72207eced415Sxw // Enter Test Mode. 72217eced415Sxw val64 = XGE_HAL_MC_RLDRAM_TEST_MODE; 72227eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72237eced415Sxw &bar0->mc_rldram_test_ctrl); 72248347601bSyl 72257eced415Sxw // Enable fg/bg tests. 72267eced415Sxw val64 = 0x0100000000000000ULL; 72277eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72287eced415Sxw &bar0->mc_driver); 72298347601bSyl 72307eced415Sxw // Enable RLDRAM configuration. 72317eced415Sxw val64 = 0x0000000000017B00ULL; 72327eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72337eced415Sxw &bar0->mc_rldram_mrs); 72348347601bSyl 72357eced415Sxw // Enable RLDRAM queues. 72367eced415Sxw val64 = 0x0000000001017B00ULL; 72377eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72387eced415Sxw &bar0->mc_rldram_mrs); 72398347601bSyl 72407eced415Sxw // Setup test ranges. 72417eced415Sxw val64 = 0x00000000001E0100ULL; 72427eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72437eced415Sxw &bar0->mc_rldram_test_add); 72448347601bSyl 72457eced415Sxw val64 = 0x00000100001F0100ULL; 72467eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72477eced415Sxw &bar0->mc_rldram_test_add_bkg); 72488347601bSyl 72497eced415Sxw // Start Reads. 72507eced415Sxw val64 = 0x0001000000010000ULL; 72517eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72527eced415Sxw &bar0->mc_rldram_test_ctrl); 72538347601bSyl 72547eced415Sxw if (__hal_device_register_poll(hldev, &bar0->mc_rldram_test_ctrl, 1, 72557eced415Sxw XGE_HAL_MC_RLDRAM_TEST_DONE, 72567eced415Sxw XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) { 72577eced415Sxw return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING; 72587eced415Sxw } 72598347601bSyl 72607eced415Sxw // Exit test mode. 72617eced415Sxw val64 = 0x0000000000000000ULL; 72627eced415Sxw xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, 72637eced415Sxw &bar0->mc_rldram_test_ctrl); 72648347601bSyl 72658347601bSyl return XGE_HAL_OK; 72668347601bSyl } 7267*19397407SSherry Moore 7268*19397407SSherry Moore /* 7269*19397407SSherry Moore * xge_hal_device_quiesce 7270*19397407SSherry Moore * @hldev: HAL device object 7271*19397407SSherry Moore * @devh : HAL device handle 7272*19397407SSherry Moore * 7273*19397407SSherry Moore * This is called by xge_quiesce to quiesce the device. 7274*19397407SSherry Moore */ 7275*19397407SSherry Moore void 7276*19397407SSherry Moore xge_hal_device_quiesce(xge_hal_device_t *hldev, xge_hal_device_h devh) 7277*19397407SSherry Moore { 7278*19397407SSherry Moore /* Turn off debugging */ 7279*19397407SSherry Moore g_xge_hal_driver->debug_level = XGE_NONE; 7280*19397407SSherry Moore g_level = &(g_xge_hal_driver->debug_level); 7281*19397407SSherry Moore 7282*19397407SSherry Moore /* Disable device */ 7283*19397407SSherry Moore (void) xge_hal_device_disable(devh); 7284*19397407SSherry Moore 7285*19397407SSherry Moore /* Disable Xframe interrupts */ 7286*19397407SSherry Moore xge_hal_device_intr_disable(devh); 7287*19397407SSherry Moore } 7288