xref: /onnv-gate/usr/src/uts/common/io/xge/hal/xgehal/xgehal-device.c (revision 8275:7c223a798022)
11256Syl150051 /*
21256Syl150051  * CDDL HEADER START
31256Syl150051  *
41256Syl150051  * The contents of this file are subject to the terms of the
51256Syl150051  * Common Development and Distribution License (the "License").
61256Syl150051  * You may not use this file except in compliance with the License.
71256Syl150051  *
81256Syl150051  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91256Syl150051  * or http://www.opensolaris.org/os/licensing.
101256Syl150051  * See the License for the specific language governing permissions
111256Syl150051  * and limitations under the License.
121256Syl150051  *
131256Syl150051  * When distributing Covered Code, include this CDDL HEADER in each
141256Syl150051  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151256Syl150051  * If applicable, add the following below this CDDL HEADER, with the
161256Syl150051  * fields enclosed by brackets "[]" replaced with your own identifying
171256Syl150051  * information: Portions Copyright [yyyy] [name of copyright owner]
181256Syl150051  *
191256Syl150051  * CDDL HEADER END
203115Syl150051  *
213115Syl150051  * Copyright (c) 2002-2006 Neterion, Inc.
221256Syl150051  */
231256Syl150051 
247656SSherry.Moore@Sun.COM /*
257656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
267656SSherry.Moore@Sun.COM  * Use is subject to license terms.
277656SSherry.Moore@Sun.COM  */
287656SSherry.Moore@Sun.COM 
291256Syl150051 #include "xgehal-device.h"
301256Syl150051 #include "xgehal-channel.h"
311256Syl150051 #include "xgehal-fifo.h"
321256Syl150051 #include "xgehal-ring.h"
331256Syl150051 #include "xgehal-driver.h"
341256Syl150051 #include "xgehal-mgmt.h"
351256Syl150051 
361256Syl150051 #define SWITCH_SIGN	0xA5A5A5A5A5A5A5A5ULL
371256Syl150051 #define	END_SIGN	0x0
381256Syl150051 
391256Syl150051 #ifdef XGE_HAL_HERC_EMULATION
401256Syl150051 #undef XGE_HAL_PROCESS_LINK_INT_IN_ISR
411256Syl150051 #endif
421256Syl150051 
431256Syl150051 /*
441256Syl150051  * Jenkins hash key length(in bytes)
451256Syl150051  */
461256Syl150051 #define XGE_HAL_JHASH_MSG_LEN 50
471256Syl150051 
481256Syl150051 /*
491256Syl150051  * mix(a,b,c) used in Jenkins hash algorithm
501256Syl150051  */
511256Syl150051 #define mix(a,b,c) { \
521256Syl150051 	a -= b; a -= c; a ^= (c>>13); \
531256Syl150051 	b -= c; b -= a; b ^= (a<<8);  \
541256Syl150051 	c -= a; c -= b; c ^= (b>>13); \
551256Syl150051 	a -= b; a -= c; a ^= (c>>12); \
561256Syl150051 	b -= c; b -= a; b ^= (a<<16); \
571256Syl150051 	c -= a; c -= b; c ^= (b>>5);  \
581256Syl150051 	a -= b; a -= c; a ^= (c>>3);  \
591256Syl150051 	b -= c; b -= a; b ^= (a<<10); \
601256Syl150051 	c -= a; c -= b; c ^= (b>>15); \
611256Syl150051 }
621256Syl150051 
631256Syl150051 
641256Syl150051 /*
651256Syl150051  * __hal_device_event_queued
661256Syl150051  * @data: pointer to xge_hal_device_t structure
671256Syl150051  *
681256Syl150051  * Will be called when new event succesfully queued.
691256Syl150051  */
701256Syl150051 void
__hal_device_event_queued(void * data,int event_type)711256Syl150051 __hal_device_event_queued(void *data, int event_type)
721256Syl150051 {
731256Syl150051 	xge_assert(((xge_hal_device_t*)data)->magic == XGE_HAL_MAGIC);
741256Syl150051 	if (g_xge_hal_driver->uld_callbacks.event_queued) {
751256Syl150051 		g_xge_hal_driver->uld_callbacks.event_queued(data, event_type);
761256Syl150051 	}
771256Syl150051 }
781256Syl150051 
791256Syl150051 /*
801256Syl150051  * __hal_pio_mem_write32_upper
811256Syl150051  *
821256Syl150051  * Endiann-aware implementation of xge_os_pio_mem_write32().
831256Syl150051  * Since Xframe has 64bit registers, we differintiate uppper and lower
841256Syl150051  * parts.
851256Syl150051  */
861256Syl150051 void
__hal_pio_mem_write32_upper(pci_dev_h pdev,pci_reg_h regh,u32 val,void * addr)871256Syl150051 __hal_pio_mem_write32_upper(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr)
881256Syl150051 {
891256Syl150051 #if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN)
901256Syl150051 	xge_os_pio_mem_write32(pdev, regh, val, addr);
911256Syl150051 #else
921256Syl150051 	xge_os_pio_mem_write32(pdev, regh, val, (void *)((char *)addr + 4));
931256Syl150051 #endif
941256Syl150051 }
951256Syl150051 
961256Syl150051 /*
971256Syl150051  * __hal_pio_mem_write32_upper
981256Syl150051  *
991256Syl150051  * Endiann-aware implementation of xge_os_pio_mem_write32().
1001256Syl150051  * Since Xframe has 64bit registers, we differintiate uppper and lower
1011256Syl150051  * parts.
1021256Syl150051  */
1031256Syl150051 void
__hal_pio_mem_write32_lower(pci_dev_h pdev,pci_reg_h regh,u32 val,void * addr)1041256Syl150051 __hal_pio_mem_write32_lower(pci_dev_h pdev, pci_reg_h regh, u32 val,
1051256Syl150051                             void *addr)
1061256Syl150051 {
1071256Syl150051 #if defined(XGE_OS_HOST_BIG_ENDIAN) && !defined(XGE_OS_PIO_LITTLE_ENDIAN)
1081256Syl150051 	xge_os_pio_mem_write32(pdev, regh, val,
1091256Syl150051                                (void *) ((char *)addr +	4));
1101256Syl150051 #else
1111256Syl150051 	xge_os_pio_mem_write32(pdev, regh, val, addr);
1121256Syl150051 #endif
1131256Syl150051 }
1141256Syl150051 
1151256Syl150051 /*
1161256Syl150051  * __hal_device_register_poll
1171256Syl150051  * @hldev: pointer to xge_hal_device_t structure
1181256Syl150051  * @reg: register to poll for
1191256Syl150051  * @op: 0 - bit reset, 1 - bit set
1201256Syl150051  * @mask: mask for logical "and" condition based on %op
1211256Syl150051  * @max_millis: maximum time to try to poll in milliseconds
1221256Syl150051  *
1231256Syl150051  * Will poll certain register for specified amount of time.
1241256Syl150051  * Will poll until masked bit is not cleared.
1251256Syl150051  */
1261256Syl150051 xge_hal_status_e
__hal_device_register_poll(xge_hal_device_t * hldev,u64 * reg,int op,u64 mask,int max_millis)1271256Syl150051 __hal_device_register_poll(xge_hal_device_t *hldev, u64 *reg,
1281256Syl150051 			   int op, u64 mask, int max_millis)
1291256Syl150051 {
1301256Syl150051 	u64 val64;
1311256Syl150051 	int i = 0;
1323115Syl150051 	xge_hal_status_e ret = XGE_HAL_FAIL;
1333115Syl150051 
1343115Syl150051 	xge_os_udelay(10);
1351256Syl150051 
1361256Syl150051 	do {
1371256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg);
1383115Syl150051 		if (op == 0 && !(val64 & mask))
1393115Syl150051 			return XGE_HAL_OK;
1403115Syl150051 		else if (op == 1 && (val64 & mask) == mask)
1413115Syl150051 			return XGE_HAL_OK;
1423115Syl150051 		xge_os_udelay(100);
1433115Syl150051 	} while (++i <= 9);
1443115Syl150051 
1453115Syl150051 	do {
1463115Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, reg);
1473115Syl150051 		if (op == 0 && !(val64 & mask))
1483115Syl150051 			return XGE_HAL_OK;
1493115Syl150051 		else if (op == 1 && (val64 & mask) == mask)
1503115Syl150051 			return XGE_HAL_OK;
1513115Syl150051 		xge_os_udelay(1000);
1523115Syl150051 	} while (++i < max_millis);
1531256Syl150051 
1541256Syl150051 	return ret;
1551256Syl150051 }
1561256Syl150051 
1571256Syl150051 /*
1581256Syl150051  * __hal_device_wait_quiescent
1591256Syl150051  * @hldev: the device
1601256Syl150051  * @hw_status: hw_status in case of error
1611256Syl150051  *
1621256Syl150051  * Will wait until device is quiescent for some blocks.
1631256Syl150051  */
1641256Syl150051 static xge_hal_status_e
__hal_device_wait_quiescent(xge_hal_device_t * hldev,u64 * hw_status)1651256Syl150051 __hal_device_wait_quiescent(xge_hal_device_t *hldev, u64 *hw_status)
1661256Syl150051 {
1671256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
1681256Syl150051 
1691256Syl150051 	/* poll and wait first */
1701256Syl150051 #ifdef XGE_HAL_HERC_EMULATION
1711256Syl150051 	(void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1,
1721256Syl150051 			(XGE_HAL_ADAPTER_STATUS_TDMA_READY |
1731256Syl150051 			 XGE_HAL_ADAPTER_STATUS_RDMA_READY |
1741256Syl150051 			 XGE_HAL_ADAPTER_STATUS_PFC_READY |
1751256Syl150051 			 XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY |
1761256Syl150051 			 XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT |
1771256Syl150051 			 XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY |
1781256Syl150051 			 XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY |
1791256Syl150051 			 XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK),
1801256Syl150051 			 XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS);
1811256Syl150051 #else
1821256Syl150051 	(void) __hal_device_register_poll(hldev, &bar0->adapter_status, 1,
1831256Syl150051 			(XGE_HAL_ADAPTER_STATUS_TDMA_READY |
1841256Syl150051 			 XGE_HAL_ADAPTER_STATUS_RDMA_READY |
1851256Syl150051 			 XGE_HAL_ADAPTER_STATUS_PFC_READY |
1861256Syl150051 			 XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY |
1871256Syl150051 			 XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT |
1881256Syl150051 			 XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY |
1891256Syl150051 			 XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY |
1901256Syl150051 			 XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK |
1911256Syl150051 			 XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK),
1921256Syl150051 			 XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS);
1931256Syl150051 #endif
1941256Syl150051 
1951256Syl150051 	return xge_hal_device_status(hldev, hw_status);
1961256Syl150051 }
1971256Syl150051 
1981256Syl150051 /**
1991256Syl150051  * xge_hal_device_is_slot_freeze
2003115Syl150051  * @devh: the device
2011256Syl150051  *
2021256Syl150051  * Returns non-zero if the slot is freezed.
2031256Syl150051  * The determination is made based on the adapter_status
2041256Syl150051  * register which will never give all FFs, unless PCI read
2051256Syl150051  * cannot go through.
2061256Syl150051  */
2071256Syl150051 int
xge_hal_device_is_slot_freeze(xge_hal_device_h devh)2081256Syl150051 xge_hal_device_is_slot_freeze(xge_hal_device_h devh)
2091256Syl150051 {
2101256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
2111256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
2121256Syl150051 	u16 device_id;
2131256Syl150051 	u64 adapter_status =
2141256Syl150051 		xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
2151256Syl150051 				      &bar0->adapter_status);
2161256Syl150051 	xge_os_pci_read16(hldev->pdev,hldev->cfgh,
2171256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, device_id),
2181256Syl150051 			&device_id);
2191256Syl150051 #ifdef TX_DEBUG
2203115Syl150051 	if (adapter_status == XGE_HAL_ALL_FOXES)
2211256Syl150051 	{
2223115Syl150051 		u64 dummy;
2233115Syl150051 		dummy = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
2243115Syl150051 						&bar0->pcc_enable);
2253115Syl150051 		printf(">>> Slot is frozen!\n");
2263115Syl150051 		brkpoint(0);
2271256Syl150051 	}
2281256Syl150051 #endif
2293115Syl150051 	return((adapter_status == XGE_HAL_ALL_FOXES) || (device_id == 0xffff));
2301256Syl150051 }
2311256Syl150051 
2321256Syl150051 
2331256Syl150051 /*
2341256Syl150051  * __hal_device_led_actifity_fix
2351256Syl150051  * @hldev: pointer to xge_hal_device_t structure
2361256Syl150051  *
2371256Syl150051  * SXE-002: Configure link and activity LED to turn it off
2381256Syl150051  */
2391256Syl150051 static void
__hal_device_led_actifity_fix(xge_hal_device_t * hldev)2401256Syl150051 __hal_device_led_actifity_fix(xge_hal_device_t *hldev)
2411256Syl150051 {
2421256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
2431256Syl150051 	u16 subid;
2441256Syl150051 	u64 val64;
2451256Syl150051 
2461256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
2471256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), &subid);
2481256Syl150051 
2491256Syl150051 	/*
2501256Syl150051 	 *  In the case of Herc, there is a new register named beacon control
2511256Syl150051 	 *  is added which was not present in Xena.
2521256Syl150051 	 *  Beacon control register in Herc is at the same offset as
2531256Syl150051 	 *  gpio control register in Xena.  It means they are one and same in
2541256Syl150051 	 *  the case of Xena. Also, gpio control register offset in Herc and
2551256Syl150051 	 *  Xena is different.
2561256Syl150051 	 *  The current register map represents Herc(It means we have
2571256Syl150051 	 *  both beacon  and gpio control registers in register map).
2581256Syl150051 	 *  WRT transition from Xena to Herc, all the code in Xena which was
2591256Syl150051 	 *  using  gpio control register for LED handling would  have to
2601256Syl150051 	 *  use beacon control register in Herc and the rest of the code
2611256Syl150051 	 *  which uses gpio control in Xena  would use the same register
2621256Syl150051 	 *  in Herc.
2631256Syl150051 	 *  WRT LED handling(following code), In the case of Herc, beacon
2641256Syl150051 	 *  control register has to be used. This is applicable for Xena also,
2651256Syl150051 	 *  since it represents the gpio control register in Xena.
2661256Syl150051 	 */
2671256Syl150051 	if ((subid & 0xFF) >= 0x07) {
2681256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
2691256Syl150051 		                            &bar0->beacon_control);
2701256Syl150051 		val64 |= 0x0000800000000000ULL;
2711256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
2721256Syl150051 				     val64, &bar0->beacon_control);
2731256Syl150051 		val64 = 0x0411040400000000ULL;
2741256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
2751256Syl150051 				    (void *) ((u8 *)bar0 + 0x2700));
2761256Syl150051 	}
2771256Syl150051 }
2781256Syl150051 
2791256Syl150051 /* Constants for Fixing the MacAddress problem seen mostly on
2801256Syl150051  * Alpha machines.
2811256Syl150051  */
2821256Syl150051 static u64 xena_fix_mac[] = {
2831256Syl150051 	0x0060000000000000ULL, 0x0060600000000000ULL,
2841256Syl150051 	0x0040600000000000ULL, 0x0000600000000000ULL,
2851256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2861256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2871256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2881256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2891256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2901256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2911256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2921256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2931256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2941256Syl150051 	0x0020600000000000ULL, 0x0060600000000000ULL,
2951256Syl150051 	0x0020600000000000ULL, 0x0000600000000000ULL,
2961256Syl150051 	0x0040600000000000ULL, 0x0060600000000000ULL,
2971256Syl150051 	END_SIGN
2981256Syl150051 };
2991256Syl150051 
3001256Syl150051 /*
3011256Syl150051  * __hal_device_fix_mac
3021256Syl150051  * @hldev: HAL device handle.
3031256Syl150051  *
3041256Syl150051  * Fix for all "FFs" MAC address problems observed on Alpha platforms.
3051256Syl150051  */
3061256Syl150051 static void
__hal_device_xena_fix_mac(xge_hal_device_t * hldev)3071256Syl150051 __hal_device_xena_fix_mac(xge_hal_device_t *hldev)
3081256Syl150051 {
3091256Syl150051 	int i = 0;
3101256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
3111256Syl150051 
3121256Syl150051 	/*
3131256Syl150051 	 *  In the case of Herc, there is a new register named beacon control
3141256Syl150051 	 *  is added which was not present in Xena.
3151256Syl150051 	 *  Beacon control register in Herc is at the same offset as
3161256Syl150051 	 *  gpio control register in Xena.  It means they are one and same in
3171256Syl150051 	 *  the case of Xena. Also, gpio control register offset in Herc and
3181256Syl150051 	 *  Xena is different.
3191256Syl150051 	 *  The current register map represents Herc(It means we have
3201256Syl150051 	 *  both beacon  and gpio control registers in register map).
3211256Syl150051 	 *  WRT transition from Xena to Herc, all the code in Xena which was
3221256Syl150051 	 *  using  gpio control register for LED handling would  have to
3231256Syl150051 	 *  use beacon control register in Herc and the rest of the code
3241256Syl150051 	 *  which uses gpio control in Xena  would use the same register
3251256Syl150051 	 *  in Herc.
3261256Syl150051 	 *  In the following code(xena_fix_mac), beacon control register has
3271256Syl150051 	 *  to be used in the case of Xena, since it represents gpio control
3281256Syl150051 	 *  register. In the case of Herc, there is no change required.
3291256Syl150051 	 */
3301256Syl150051 	while (xena_fix_mac[i] != END_SIGN) {
3311256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
3321256Syl150051 				xena_fix_mac[i++], &bar0->beacon_control);
3331256Syl150051 		xge_os_mdelay(1);
3341256Syl150051 	}
3351256Syl150051 }
3361256Syl150051 
3371256Syl150051 /*
3381256Syl150051  * xge_hal_device_bcast_enable
3391256Syl150051  * @hldev: HAL device handle.
3401256Syl150051  *
3411256Syl150051  * Enable receiving broadcasts.
3421256Syl150051  * The host must first write RMAC_CFG_KEY "key"
3431256Syl150051  * register, and then - MAC_CFG register.
3441256Syl150051  */
3451256Syl150051 void
xge_hal_device_bcast_enable(xge_hal_device_h devh)3461256Syl150051 xge_hal_device_bcast_enable(xge_hal_device_h devh)
3471256Syl150051 {
3481256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
3491256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
3501256Syl150051 	u64 val64;
3511256Syl150051 
3521256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
3531256Syl150051 	&bar0->mac_cfg);
3541256Syl150051 		val64 |= XGE_HAL_MAC_RMAC_BCAST_ENABLE;
3551256Syl150051 
3561256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
3571256Syl150051 		XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
3581256Syl150051 
3591256Syl150051     __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
3601256Syl150051 		(u32)(val64 >> 32), &bar0->mac_cfg);
3611256Syl150051 
3623115Syl150051 	xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s",
3631256Syl150051 		(unsigned long long)val64,
3641256Syl150051 		hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled");
3651256Syl150051 }
3661256Syl150051 
3671256Syl150051 /*
3681256Syl150051  * xge_hal_device_bcast_disable
3691256Syl150051  * @hldev: HAL device handle.
3701256Syl150051  *
3711256Syl150051  * Disable receiving broadcasts.
3721256Syl150051  * The host must first write RMAC_CFG_KEY "key"
3731256Syl150051  * register, and then - MAC_CFG register.
3741256Syl150051  */
3751256Syl150051 void
xge_hal_device_bcast_disable(xge_hal_device_h devh)3761256Syl150051 xge_hal_device_bcast_disable(xge_hal_device_h devh)
3771256Syl150051 {
3781256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
3791256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
3801256Syl150051 	u64 val64;
3811256Syl150051 
3821256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
3831256Syl150051 	&bar0->mac_cfg);
3841256Syl150051 
3851256Syl150051 	val64 &= ~(XGE_HAL_MAC_RMAC_BCAST_ENABLE);
3861256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
3871256Syl150051 		     XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
3881256Syl150051 
3891256Syl150051         __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
3901256Syl150051 		    (u32)(val64 >> 32), &bar0->mac_cfg);
3911256Syl150051 
3923115Syl150051 	xge_debug_device(XGE_TRACE, "mac_cfg 0x"XGE_OS_LLXFMT": broadcast %s",
3931256Syl150051 		(unsigned long long)val64,
3941256Syl150051 		hldev->config.mac.rmac_bcast_en ? "enabled" : "disabled");
3951256Syl150051 }
3961256Syl150051 
3971256Syl150051 /*
3981256Syl150051  * __hal_device_shared_splits_configure
3991256Syl150051  * @hldev: HAL device handle.
4001256Syl150051  *
4011256Syl150051  * TxDMA will stop Read request if the number of read split had exceeded
4021256Syl150051  * the limit set by shared_splits
4031256Syl150051  */
4041256Syl150051 static void
__hal_device_shared_splits_configure(xge_hal_device_t * hldev)4051256Syl150051 __hal_device_shared_splits_configure(xge_hal_device_t *hldev)
4061256Syl150051 {
4071256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
4081256Syl150051 	u64 val64;
4091256Syl150051 
4101256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
4111256Syl150051 	                            &bar0->pic_control);
4121256Syl150051 	val64 |=
4131256Syl150051 	XGE_HAL_PIC_CNTL_SHARED_SPLITS(hldev->config.shared_splits);
4141256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
4151256Syl150051 			     &bar0->pic_control);
4161256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "shared splits configured");
4171256Syl150051 }
4181256Syl150051 
4191256Syl150051 /*
4201256Syl150051  * __hal_device_rmac_padding_configure
4211256Syl150051  * @hldev: HAL device handle.
4221256Syl150051  *
4231256Syl150051  * Configure RMAC frame padding. Depends on configuration, it
4241256Syl150051  * can be send to host or removed by MAC.
4251256Syl150051  */
4261256Syl150051 static void
__hal_device_rmac_padding_configure(xge_hal_device_t * hldev)4271256Syl150051 __hal_device_rmac_padding_configure(xge_hal_device_t *hldev)
4281256Syl150051 {
4291256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
4301256Syl150051 	u64 val64;
4311256Syl150051 
4321256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
4331256Syl150051 		    XGE_HAL_RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
4341256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
4351256Syl150051 	&bar0->mac_cfg);
4361256Syl150051 	val64 &= ( ~XGE_HAL_MAC_RMAC_ALL_ADDR_ENABLE );
4371256Syl150051 	val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE );
4381256Syl150051 	val64 |= XGE_HAL_MAC_CFG_TMAC_APPEND_PAD;
4391256Syl150051 
4401256Syl150051 	/*
4411256Syl150051 	 * If the RTH enable bit is not set, strip the FCS
4421256Syl150051 	 */
4431256Syl150051 	if (!hldev->config.rth_en ||
4441256Syl150051 	    !(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
4451256Syl150051 			   &bar0->rts_rth_cfg) & XGE_HAL_RTS_RTH_EN)) {
4461256Syl150051 		val64 |= XGE_HAL_MAC_CFG_RMAC_STRIP_FCS;
4471256Syl150051 	}
4481256Syl150051 
4491256Syl150051 	val64 &= ( ~XGE_HAL_MAC_CFG_RMAC_STRIP_PAD );
4501256Syl150051 	val64 |= XGE_HAL_MAC_RMAC_DISCARD_PFRM;
4511256Syl150051 
4521256Syl150051 	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
4531256Syl150051 		    (u32)(val64 >> 32), (char*)&bar0->mac_cfg);
4541256Syl150051 	xge_os_mdelay(1);
4551256Syl150051 
4561256Syl150051 	xge_debug_device(XGE_TRACE,
4573115Syl150051 		  "mac_cfg 0x"XGE_OS_LLXFMT": frame padding configured",
4583115Syl150051 		  (unsigned long long)val64);
4591256Syl150051 }
4601256Syl150051 
4611256Syl150051 /*
4621256Syl150051  * __hal_device_pause_frames_configure
4631256Syl150051  * @hldev: HAL device handle.
4641256Syl150051  *
4651256Syl150051  * Set Pause threshold.
4661256Syl150051  *
4671256Syl150051  * Pause frame is generated if the amount of data outstanding
4681256Syl150051  * on any queue exceeded the ratio of
4691256Syl150051  * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256
4701256Syl150051  */
4711256Syl150051 static void
__hal_device_pause_frames_configure(xge_hal_device_t * hldev)4721256Syl150051 __hal_device_pause_frames_configure(xge_hal_device_t *hldev)
4731256Syl150051 {
4741256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
4751256Syl150051 	int i;
4761256Syl150051 	u64 val64;
4771256Syl150051 
4781256Syl150051 	switch (hldev->config.mac.media) {
4791256Syl150051 		case XGE_HAL_MEDIA_SR:
4801256Syl150051 		case XGE_HAL_MEDIA_SW:
4811256Syl150051 			val64=0xfffbfffbfffbfffbULL;
4821256Syl150051 			break;
4831256Syl150051 		case XGE_HAL_MEDIA_LR:
4841256Syl150051 		case XGE_HAL_MEDIA_LW:
4851256Syl150051 			val64=0xffbbffbbffbbffbbULL;
4861256Syl150051 			break;
4871256Syl150051 		case XGE_HAL_MEDIA_ER:
4881256Syl150051 		case XGE_HAL_MEDIA_EW:
4891256Syl150051 		default:
4901256Syl150051 			val64=0xffbbffbbffbbffbbULL;
4911256Syl150051 			break;
4921256Syl150051 	}
4931256Syl150051 
4941256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
4951256Syl150051 			val64, &bar0->mc_pause_thresh_q0q3);
4961256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
4971256Syl150051 			val64, &bar0->mc_pause_thresh_q4q7);
4981256Syl150051 
4991256Syl150051 	/* Set the time value  to be inserted in the pause frame generated
5001256Syl150051 	 * by Xframe */
5011256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
5021256Syl150051 	                            &bar0->rmac_pause_cfg);
5031256Syl150051 	if (hldev->config.mac.rmac_pause_gen_en)
5041256Syl150051 		val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN;
5051256Syl150051 	else
5061256Syl150051 		val64 &= ~(XGE_HAL_RMAC_PAUSE_GEN_EN);
5071256Syl150051 	if (hldev->config.mac.rmac_pause_rcv_en)
5081256Syl150051 		val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN;
5091256Syl150051 	else
5101256Syl150051 		val64 &= ~(XGE_HAL_RMAC_PAUSE_RCV_EN);
5111256Syl150051 	val64 &= ~(XGE_HAL_RMAC_PAUSE_HG_PTIME(0xffff));
5121256Syl150051 	val64 |= XGE_HAL_RMAC_PAUSE_HG_PTIME(hldev->config.mac.rmac_pause_time);
5131256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
5141256Syl150051 			     &bar0->rmac_pause_cfg);
5151256Syl150051 
5161256Syl150051 	val64 = 0;
5171256Syl150051 	for (i = 0; i<4; i++) {
5181256Syl150051 		val64 |=
5191256Syl150051 		     (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q0q3)
5201256Syl150051 							<<(i*2*8));
5211256Syl150051 	}
5221256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
5231256Syl150051 			     &bar0->mc_pause_thresh_q0q3);
5241256Syl150051 
5251256Syl150051 	val64 = 0;
5261256Syl150051 	for (i = 0; i<4; i++) {
5271256Syl150051 		val64 |=
5281256Syl150051 		     (((u64)0xFF00|hldev->config.mac.mc_pause_threshold_q4q7)
5291256Syl150051 							<<(i*2*8));
5301256Syl150051 	}
5311256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
5321256Syl150051 			     &bar0->mc_pause_thresh_q4q7);
5331256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "pause frames configured");
5341256Syl150051 }
5351256Syl150051 
5361256Syl150051 /*
5371256Syl150051  * Herc's clock rate doubled, unless the slot is 33MHz.
5381256Syl150051  */
__hal_fix_time_ival_herc(xge_hal_device_t * hldev,unsigned int time_ival)5391256Syl150051 unsigned int __hal_fix_time_ival_herc(xge_hal_device_t *hldev,
5401256Syl150051 				      unsigned int time_ival)
5411256Syl150051 {
5421256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)
5431256Syl150051 		return time_ival;
5441256Syl150051 
5451256Syl150051 	xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC);
5461256Syl150051 
5471256Syl150051 	if (hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN &&
5481256Syl150051 	    hldev->bus_frequency != XGE_HAL_PCI_BUS_FREQUENCY_33MHZ)
5491256Syl150051 		time_ival *= 2;
5501256Syl150051 
5511256Syl150051 	return time_ival;
5521256Syl150051 }
5531256Syl150051 
5541256Syl150051 
5551256Syl150051 /*
5561256Syl150051  * __hal_device_bus_master_disable
5571256Syl150051  * @hldev: HAL device handle.
5581256Syl150051  *
5591256Syl150051  * Disable bus mastership.
5601256Syl150051  */
5611256Syl150051 static void
__hal_device_bus_master_disable(xge_hal_device_t * hldev)5621256Syl150051 __hal_device_bus_master_disable (xge_hal_device_t *hldev)
5631256Syl150051 {
5641256Syl150051 	u16 cmd;
5651256Syl150051 	u16 bus_master = 4;
5661256Syl150051 
5671256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
5681256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, command), &cmd);
5691256Syl150051 	cmd &= ~bus_master;
5701256Syl150051 	xge_os_pci_write16(hldev->pdev, hldev->cfgh,
5711256Syl150051 			 xge_offsetof(xge_hal_pci_config_le_t, command), cmd);
5721256Syl150051 }
5731256Syl150051 
5741256Syl150051 /*
5751256Syl150051  * __hal_device_bus_master_enable
5761256Syl150051  * @hldev: HAL device handle.
5771256Syl150051  *
5781256Syl150051  * Disable bus mastership.
5791256Syl150051  */
5801256Syl150051 static void
__hal_device_bus_master_enable(xge_hal_device_t * hldev)5811256Syl150051 __hal_device_bus_master_enable (xge_hal_device_t *hldev)
5821256Syl150051 {
5831256Syl150051 	u16 cmd;
5841256Syl150051 	u16 bus_master = 4;
5851256Syl150051 
5861256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
5871256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, command), &cmd);
5881256Syl150051 
5891256Syl150051 	/* already enabled? do nothing */
5901256Syl150051 	if (cmd & bus_master)
5911256Syl150051 		return;
5921256Syl150051 
5931256Syl150051 	cmd |= bus_master;
5941256Syl150051 	xge_os_pci_write16(hldev->pdev, hldev->cfgh,
5951256Syl150051 			 xge_offsetof(xge_hal_pci_config_le_t, command), cmd);
5961256Syl150051 }
5971256Syl150051 /*
5981256Syl150051  * __hal_device_intr_mgmt
5991256Syl150051  * @hldev: HAL device handle.
6001256Syl150051  * @mask: mask indicating which Intr block must be modified.
6011256Syl150051  * @flag: if true - enable, otherwise - disable interrupts.
6021256Syl150051  *
6031256Syl150051  * Disable or enable device interrupts. Mask is used to specify
6041256Syl150051  * which hardware blocks should produce interrupts. For details
6051256Syl150051  * please refer to Xframe User Guide.
6061256Syl150051  */
6071256Syl150051 static void
__hal_device_intr_mgmt(xge_hal_device_t * hldev,u64 mask,int flag)6081256Syl150051 __hal_device_intr_mgmt(xge_hal_device_t *hldev, u64 mask, int flag)
6091256Syl150051 {
6101256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
6111256Syl150051 	u64 val64 = 0, temp64 = 0;
6121256Syl150051 	u64 gim, gim_saved;
6131256Syl150051 
6141256Syl150051 	gim_saved = gim = xge_os_pio_mem_read64(hldev->pdev,
6151256Syl150051                               hldev->regh0, &bar0->general_int_mask);
6161256Syl150051 
6171256Syl150051 	/* Top level interrupt classification */
6181256Syl150051 	/* PIC Interrupts */
6191256Syl150051 	if ((mask & (XGE_HAL_TX_PIC_INTR/* | XGE_HAL_RX_PIC_INTR*/))) {
6201256Syl150051 		/* Enable PIC Intrs in the general intr mask register */
6211256Syl150051 		val64 = XGE_HAL_TXPIC_INT_M/* | XGE_HAL_PIC_RX_INT_M*/;
6221256Syl150051 		if (flag) {
6231256Syl150051 			gim &= ~((u64) val64);
6241256Syl150051 			temp64 = xge_os_pio_mem_read64(hldev->pdev,
6251256Syl150051 					hldev->regh0, &bar0->pic_int_mask);
6261256Syl150051 
6271256Syl150051 			temp64 &= ~XGE_HAL_PIC_INT_TX;
6281256Syl150051 #ifdef  XGE_HAL_PROCESS_LINK_INT_IN_ISR
6291256Syl150051 			if (xge_hal_device_check_id(hldev) ==
6301256Syl150051 							XGE_HAL_CARD_HERC) {
6311256Syl150051 				temp64 &= ~XGE_HAL_PIC_INT_MISC;
6321256Syl150051 			}
6331256Syl150051 #endif
6341256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6351256Syl150051 					     temp64, &bar0->pic_int_mask);
6361256Syl150051 #ifdef  XGE_HAL_PROCESS_LINK_INT_IN_ISR
6371256Syl150051 			if (xge_hal_device_check_id(hldev) ==
6381256Syl150051 							XGE_HAL_CARD_HERC) {
6391256Syl150051 				/*
6401256Syl150051 				 * Unmask only Link Up interrupt
6411256Syl150051 				 */
6421256Syl150051 				temp64 = xge_os_pio_mem_read64(hldev->pdev,
6431256Syl150051 					hldev->regh0, &bar0->misc_int_mask);
6441256Syl150051 				temp64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT;
6451256Syl150051 				xge_os_pio_mem_write64(hldev->pdev,
6461256Syl150051 					      hldev->regh0, temp64,
6471256Syl150051 					      &bar0->misc_int_mask);
6481256Syl150051 				xge_debug_device(XGE_TRACE,
6493115Syl150051 					"unmask link up flag "XGE_OS_LLXFMT,
6501256Syl150051 					(unsigned long long)temp64);
6511256Syl150051 			}
6521256Syl150051 #endif
6531256Syl150051 		} else { /* flag == 0 */
6541256Syl150051 
6551256Syl150051 #ifdef  XGE_HAL_PROCESS_LINK_INT_IN_ISR
6561256Syl150051 			if (xge_hal_device_check_id(hldev) ==
6571256Syl150051 							XGE_HAL_CARD_HERC) {
6581256Syl150051 				/*
6591256Syl150051 				 * Mask both Link Up and Down interrupts
6601256Syl150051 				 */
6611256Syl150051 				temp64 = xge_os_pio_mem_read64(hldev->pdev,
6621256Syl150051 					hldev->regh0, &bar0->misc_int_mask);
6631256Syl150051 				temp64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT;
6641256Syl150051 				temp64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT;
6651256Syl150051 				xge_os_pio_mem_write64(hldev->pdev,
6661256Syl150051 					      hldev->regh0, temp64,
6671256Syl150051 					      &bar0->misc_int_mask);
6681256Syl150051 				xge_debug_device(XGE_TRACE,
6693115Syl150051 					"mask link up/down flag "XGE_OS_LLXFMT,
6701256Syl150051 					(unsigned long long)temp64);
6711256Syl150051 			}
6721256Syl150051 #endif
6731256Syl150051 			/* Disable PIC Intrs in the general intr mask
6741256Syl150051 			 * register */
6751256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6761256Syl150051 					     XGE_HAL_ALL_INTRS_DIS,
6771256Syl150051 			                     &bar0->pic_int_mask);
6781256Syl150051 			gim |= val64;
6791256Syl150051 		}
6801256Syl150051 	}
6811256Syl150051 
6821256Syl150051 	/*  DMA Interrupts */
6831256Syl150051 	/*  Enabling/Disabling Tx DMA interrupts */
6841256Syl150051 	if (mask & XGE_HAL_TX_DMA_INTR) {
6851256Syl150051 		/*  Enable TxDMA Intrs in the general intr mask register */
6861256Syl150051 		val64 = XGE_HAL_TXDMA_INT_M;
6871256Syl150051 		if (flag) {
6881256Syl150051 			gim &= ~((u64) val64);
6896937Sxw161283 			/* Enable all TxDMA interrupts */
6906937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6916937Sxw161283 					     0x0, &bar0->txdma_int_mask);
6926937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6936937Sxw161283 					     0x0, &bar0->pfc_err_mask);
6946937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6956937Sxw161283 					     0x0, &bar0->tda_err_mask);
6961256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6976937Sxw161283 					     0x0, &bar0->pcc_err_mask);
6986937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
6996937Sxw161283 					     0x0, &bar0->tti_err_mask);
7001256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7016937Sxw161283 					     0x0, &bar0->lso_err_mask);
7026937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7036937Sxw161283 					     0x0, &bar0->tpa_err_mask);
7046937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7056937Sxw161283 					     0x0, &bar0->sm_err_mask);
7061256Syl150051 
7071256Syl150051 		} else { /* flag == 0 */
7081256Syl150051 
7091256Syl150051 			/*  Disable TxDMA Intrs in the general intr mask
7101256Syl150051 			 *  register */
7111256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7121256Syl150051 					     XGE_HAL_ALL_INTRS_DIS,
7131256Syl150051 			                     &bar0->txdma_int_mask);
7141256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7151256Syl150051 					     XGE_HAL_ALL_INTRS_DIS,
7161256Syl150051 			                     &bar0->pfc_err_mask);
7171256Syl150051 
7181256Syl150051 			gim |= val64;
7191256Syl150051 		}
7201256Syl150051 	}
7211256Syl150051 
7221256Syl150051 	/*  Enabling/Disabling Rx DMA interrupts */
7231256Syl150051 	if (mask & XGE_HAL_RX_DMA_INTR) {
7241256Syl150051 		/*  Enable RxDMA Intrs in the general intr mask register */
7251256Syl150051 		val64 = XGE_HAL_RXDMA_INT_M;
7261256Syl150051 		if (flag) {
7271256Syl150051 
7281256Syl150051 			gim &= ~((u64) val64);
7291256Syl150051 			/* All RxDMA block interrupts are disabled for now
7301256Syl150051 			 * TODO */
7311256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7321256Syl150051 					     XGE_HAL_ALL_INTRS_DIS,
7331256Syl150051 			                     &bar0->rxdma_int_mask);
7341256Syl150051 
7351256Syl150051 		} else { /* flag == 0 */
7361256Syl150051 
7371256Syl150051 			/*  Disable RxDMA Intrs in the general intr mask
7381256Syl150051 			 *  register */
7391256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7401256Syl150051 					     XGE_HAL_ALL_INTRS_DIS,
7411256Syl150051 			                     &bar0->rxdma_int_mask);
7421256Syl150051 
7431256Syl150051 			gim |= val64;
7441256Syl150051 		}
7451256Syl150051 	}
7461256Syl150051 
7471256Syl150051 	/*  MAC Interrupts */
7481256Syl150051 	/*  Enabling/Disabling MAC interrupts */
7491256Syl150051 	if (mask & (XGE_HAL_TX_MAC_INTR | XGE_HAL_RX_MAC_INTR)) {
7501256Syl150051 		val64 = XGE_HAL_TXMAC_INT_M | XGE_HAL_RXMAC_INT_M;
7511256Syl150051 		if (flag) {
7521256Syl150051 
7531256Syl150051 			gim &= ~((u64) val64);
7541256Syl150051 
7551256Syl150051 			/* All MAC block error inter. are disabled for now. */
7561256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7571256Syl150051 			     XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask);
7581256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7591256Syl150051 			     XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask);
7601256Syl150051 
7611256Syl150051 		} else { /* flag == 0 */
7621256Syl150051 
7631256Syl150051 			/* Disable MAC Intrs in the general intr mask
7641256Syl150051 			 * register */
7651256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7661256Syl150051 			     XGE_HAL_ALL_INTRS_DIS, &bar0->mac_int_mask);
7671256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7681256Syl150051 			     XGE_HAL_ALL_INTRS_DIS, &bar0->mac_rmac_err_mask);
7691256Syl150051 
7701256Syl150051 			gim |= val64;
7711256Syl150051 		}
7721256Syl150051 	}
7731256Syl150051 
7741256Syl150051 	/*  XGXS Interrupts */
7751256Syl150051 	if (mask & (XGE_HAL_TX_XGXS_INTR | XGE_HAL_RX_XGXS_INTR)) {
7761256Syl150051 		val64 = XGE_HAL_TXXGXS_INT_M | XGE_HAL_RXXGXS_INT_M;
7771256Syl150051 		if (flag) {
7781256Syl150051 
7791256Syl150051 			gim &= ~((u64) val64);
7801256Syl150051 			/* All XGXS block error interrupts are disabled for now
7811256Syl150051 			 * TODO */
7821256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7831256Syl150051 			     XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask);
7841256Syl150051 
7851256Syl150051 		} else { /* flag == 0 */
7861256Syl150051 
7871256Syl150051 			/* Disable MC Intrs in the general intr mask register */
7881256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
7891256Syl150051 				XGE_HAL_ALL_INTRS_DIS, &bar0->xgxs_int_mask);
7901256Syl150051 
7911256Syl150051 			gim |= val64;
7921256Syl150051 		}
7931256Syl150051 	}
7941256Syl150051 
7951256Syl150051 	/*  Memory Controller(MC) interrupts */
7961256Syl150051 	if (mask & XGE_HAL_MC_INTR) {
7971256Syl150051 		val64 = XGE_HAL_MC_INT_M;
7981256Syl150051 		if (flag) {
7991256Syl150051 
8001256Syl150051 			gim &= ~((u64) val64);
8011256Syl150051 
8021256Syl150051 			/* Enable all MC blocks error interrupts */
8031256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8041256Syl150051 				     0x0ULL, &bar0->mc_int_mask);
8051256Syl150051 
8061256Syl150051 		} else { /* flag == 0 */
8071256Syl150051 
8081256Syl150051 			/* Disable MC Intrs in the general intr mask
8091256Syl150051 			 * register */
8101256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8111256Syl150051 				     XGE_HAL_ALL_INTRS_DIS, &bar0->mc_int_mask);
8121256Syl150051 
8131256Syl150051 			gim |= val64;
8141256Syl150051 		}
8151256Syl150051 	}
8161256Syl150051 
8171256Syl150051 
8181256Syl150051 	/*  Tx traffic interrupts */
8191256Syl150051 	if (mask & XGE_HAL_TX_TRAFFIC_INTR) {
8201256Syl150051 		val64 = XGE_HAL_TXTRAFFIC_INT_M;
8211256Syl150051 		if (flag) {
8221256Syl150051 
8231256Syl150051 			gim &= ~((u64) val64);
8241256Syl150051 
8251256Syl150051 			/* Enable all the Tx side interrupts */
8261256Syl150051 			/* '0' Enables all 64 TX interrupt levels. */
8271256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0,
8281256Syl150051 			                    &bar0->tx_traffic_mask);
8291256Syl150051 
8301256Syl150051 		} else { /* flag == 0 */
8311256Syl150051 
8321256Syl150051 			/* Disable Tx Traffic Intrs in the general intr mask
8331256Syl150051 			 * register. */
8341256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8351256Syl150051 			                     XGE_HAL_ALL_INTRS_DIS,
8361256Syl150051 			                     &bar0->tx_traffic_mask);
8371256Syl150051 			gim |= val64;
8381256Syl150051 		}
8391256Syl150051 	}
8401256Syl150051 
8411256Syl150051 	/*  Rx traffic interrupts */
8421256Syl150051 	if (mask & XGE_HAL_RX_TRAFFIC_INTR) {
8431256Syl150051 		val64 = XGE_HAL_RXTRAFFIC_INT_M;
8441256Syl150051 		if (flag) {
8451256Syl150051 			gim &= ~((u64) val64);
8461256Syl150051 			/* '0' Enables all 8 RX interrupt levels. */
8471256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x0,
8481256Syl150051 			                    &bar0->rx_traffic_mask);
8491256Syl150051 
8501256Syl150051 		} else { /* flag == 0 */
8511256Syl150051 
8521256Syl150051 			/* Disable Rx Traffic Intrs in the general intr mask
8531256Syl150051 			 * register.
8541256Syl150051 			 */
8551256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8561256Syl150051 			                     XGE_HAL_ALL_INTRS_DIS,
8571256Syl150051 			                     &bar0->rx_traffic_mask);
8581256Syl150051 
8591256Syl150051 			gim |= val64;
8601256Syl150051 		}
8611256Syl150051 	}
8621256Syl150051 
8631256Syl150051 	/* Sched Timer interrupt */
8641256Syl150051 	if (mask & XGE_HAL_SCHED_INTR) {
8651256Syl150051 		if (flag) {
8661256Syl150051 			temp64 = xge_os_pio_mem_read64(hldev->pdev,
8671256Syl150051 					hldev->regh0, &bar0->txpic_int_mask);
8681256Syl150051 			temp64 &= ~XGE_HAL_TXPIC_INT_SCHED_INTR;
8691256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8701256Syl150051 					temp64, &bar0->txpic_int_mask);
8711256Syl150051 
8721256Syl150051 			xge_hal_device_sched_timer(hldev,
8731256Syl150051 					hldev->config.sched_timer_us,
8741256Syl150051 					hldev->config.sched_timer_one_shot);
8751256Syl150051 		} else {
8761256Syl150051 			temp64 = xge_os_pio_mem_read64(hldev->pdev,
8771256Syl150051 					hldev->regh0, &bar0->txpic_int_mask);
8781256Syl150051 			temp64 |= XGE_HAL_TXPIC_INT_SCHED_INTR;
8791256Syl150051 
8801256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8811256Syl150051 					temp64, &bar0->txpic_int_mask);
8821256Syl150051 
8831256Syl150051 			xge_hal_device_sched_timer(hldev,
8841256Syl150051 					XGE_HAL_SCHED_TIMER_DISABLED,
8851256Syl150051 					XGE_HAL_SCHED_TIMER_ON_SHOT_ENABLE);
8861256Syl150051 		}
8871256Syl150051 	}
8881256Syl150051 
8891256Syl150051 	if (gim != gim_saved) {
8901256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, gim,
8911256Syl150051 			&bar0->general_int_mask);
8923115Syl150051 		xge_debug_device(XGE_TRACE, "general_int_mask updated "
8933115Syl150051 			 XGE_OS_LLXFMT" => "XGE_OS_LLXFMT,
8941256Syl150051 			(unsigned long long)gim_saved, (unsigned long long)gim);
8951256Syl150051 	}
8961256Syl150051 }
8971256Syl150051 
8981256Syl150051 /*
8993115Syl150051  * __hal_device_bimodal_configure
9003115Syl150051  * @hldev: HAL device handle.
9013115Syl150051  *
9023115Syl150051  * Bimodal parameters initialization.
9033115Syl150051  */
9043115Syl150051 static void
__hal_device_bimodal_configure(xge_hal_device_t * hldev)9053115Syl150051 __hal_device_bimodal_configure(xge_hal_device_t *hldev)
9063115Syl150051 {
9073115Syl150051 	int i;
9083115Syl150051 
9093115Syl150051 	for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) {
9103115Syl150051 		xge_hal_tti_config_t *tti;
9113115Syl150051 		xge_hal_rti_config_t *rti;
9123115Syl150051 
9133115Syl150051 		if (!hldev->config.ring.queue[i].configured)
9143115Syl150051 			continue;
9153115Syl150051 		rti = &hldev->config.ring.queue[i].rti;
9163115Syl150051 		tti = &hldev->bimodal_tti[i];
9173115Syl150051 
9183115Syl150051 		tti->enabled = 1;
9193115Syl150051 		tti->urange_a = hldev->bimodal_urange_a_en * 10;
9203115Syl150051 		tti->urange_b = 20;
9213115Syl150051 		tti->urange_c = 30;
9223115Syl150051 		tti->ufc_a = hldev->bimodal_urange_a_en * 8;
9233115Syl150051 		tti->ufc_b = 16;
9243115Syl150051 		tti->ufc_c = 32;
9253115Syl150051 		tti->ufc_d = 64;
9263115Syl150051 		tti->timer_val_us = hldev->bimodal_timer_val_us;
9273115Syl150051 		tti->timer_ac_en = 1;
9283115Syl150051 		tti->timer_ci_en = 0;
9293115Syl150051 
9303115Syl150051 		rti->urange_a = 10;
9313115Syl150051 		rti->urange_b = 20;
9323115Syl150051 		rti->urange_c = 30;
9333115Syl150051 		rti->ufc_a = 1; /* <= for netpipe type of tests */
9343115Syl150051 		rti->ufc_b = 4;
9353115Syl150051 		rti->ufc_c = 4;
9363115Syl150051 		rti->ufc_d = 4; /* <= 99% of a bandwidth traffic counts here */
9373115Syl150051 		rti->timer_ac_en = 1;
9383115Syl150051 		rti->timer_val_us = 5; /* for optimal bus efficiency usage */
9393115Syl150051 	}
9403115Syl150051 }
9413115Syl150051 
9423115Syl150051 /*
9433115Syl150051  * __hal_device_tti_apply
9443115Syl150051  * @hldev: HAL device handle.
9453115Syl150051  *
9463115Syl150051  * apply TTI configuration.
9473115Syl150051  */
9483115Syl150051 static xge_hal_status_e
__hal_device_tti_apply(xge_hal_device_t * hldev,xge_hal_tti_config_t * tti,int num,int runtime)9493115Syl150051 __hal_device_tti_apply(xge_hal_device_t *hldev, xge_hal_tti_config_t *tti,
9503115Syl150051 		       int num, int runtime)
9513115Syl150051 {
9523115Syl150051 	u64 val64, data1 = 0, data2 = 0;
9533115Syl150051 	xge_hal_pci_bar0_t *bar0;
9543115Syl150051 
9553115Syl150051 	if (runtime)
9563115Syl150051 		bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
9573115Syl150051 	else
9583115Syl150051 		bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
9593115Syl150051 
9603115Syl150051 	if (tti->timer_val_us) {
9613115Syl150051 		unsigned int tx_interval;
9623115Syl150051 
9633115Syl150051 		if (hldev->config.pci_freq_mherz) {
9643115Syl150051 			tx_interval = hldev->config.pci_freq_mherz *
9653115Syl150051 					tti->timer_val_us / 64;
9663115Syl150051 			tx_interval =
9673115Syl150051 				__hal_fix_time_ival_herc(hldev,
9683115Syl150051 							 tx_interval);
9693115Syl150051 		} else {
9703115Syl150051 			tx_interval = tti->timer_val_us;
9713115Syl150051 		}
9723115Syl150051 		data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_VAL(tx_interval);
9733115Syl150051 		if (tti->timer_ac_en) {
9743115Syl150051 			data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_AC_EN;
9753115Syl150051 		}
9763115Syl150051 		if (tti->timer_ci_en) {
9773115Syl150051 			data1 |= XGE_HAL_TTI_DATA1_MEM_TX_TIMER_CI_EN;
9783115Syl150051 		}
9793115Syl150051 
9803115Syl150051 		if (!runtime) {
9813115Syl150051 			xge_debug_device(XGE_TRACE, "TTI[%d] timer enabled to %d, ci %s",
9823115Syl150051 				  num, tx_interval, tti->timer_ci_en ?
9833115Syl150051 				  "enabled": "disabled");
9843115Syl150051 		}
9853115Syl150051 	}
9863115Syl150051 
9873115Syl150051 	if (tti->urange_a ||
9883115Syl150051 	    tti->urange_b ||
9893115Syl150051 	    tti->urange_c ||
9903115Syl150051 	    tti->ufc_a ||
9913115Syl150051 	    tti->ufc_b ||
9923115Syl150051 	    tti->ufc_c ||
9933115Syl150051 	    tti->ufc_d ) {
9943115Syl150051 		data1 |= XGE_HAL_TTI_DATA1_MEM_TX_URNG_A(tti->urange_a) |
9953115Syl150051 			 XGE_HAL_TTI_DATA1_MEM_TX_URNG_B(tti->urange_b) |
9963115Syl150051 			 XGE_HAL_TTI_DATA1_MEM_TX_URNG_C(tti->urange_c);
9973115Syl150051 
9983115Syl150051 		data2 |= XGE_HAL_TTI_DATA2_MEM_TX_UFC_A(tti->ufc_a) |
9993115Syl150051 			 XGE_HAL_TTI_DATA2_MEM_TX_UFC_B(tti->ufc_b) |
10003115Syl150051 			 XGE_HAL_TTI_DATA2_MEM_TX_UFC_C(tti->ufc_c) |
10013115Syl150051 			 XGE_HAL_TTI_DATA2_MEM_TX_UFC_D(tti->ufc_d);
10023115Syl150051 	}
10033115Syl150051 
10046937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
10056937Sxw161283 	    data1, &bar0->tti_data1_mem);
10066937Sxw161283 	(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
10076937Sxw161283 	    &bar0->tti_data1_mem);
10086937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
10096937Sxw161283 	    data2, &bar0->tti_data2_mem);
10106937Sxw161283 	(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
10116937Sxw161283 	    &bar0->tti_data2_mem);
10123115Syl150051 	xge_os_wmb();
10133115Syl150051 
10143115Syl150051 	val64 = XGE_HAL_TTI_CMD_MEM_WE | XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD |
10153115Syl150051 	      XGE_HAL_TTI_CMD_MEM_OFFSET(num);
10163115Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
10173115Syl150051 		&bar0->tti_command_mem);
10183115Syl150051 
10193115Syl150051 	if (!runtime && __hal_device_register_poll(hldev, &bar0->tti_command_mem,
10203115Syl150051 		   0, XGE_HAL_TTI_CMD_MEM_STROBE_NEW_CMD,
10213115Syl150051 		   XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
10223115Syl150051 		/* upper layer may require to repeat */
10233115Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
10243115Syl150051 	}
10253115Syl150051 
10263115Syl150051 	if (!runtime) {
10273115Syl150051 		xge_debug_device(XGE_TRACE, "TTI[%d] configured: tti_data1_mem 0x"
10283115Syl150051 		   XGE_OS_LLXFMT, num,
10293115Syl150051 		   (unsigned long long)xge_os_pio_mem_read64(hldev->pdev,
10303115Syl150051 		   hldev->regh0, &bar0->tti_data1_mem));
10313115Syl150051 	}
10323115Syl150051 
10333115Syl150051 	return XGE_HAL_OK;
10343115Syl150051 }
10353115Syl150051 
10363115Syl150051 /*
10373115Syl150051  * __hal_device_tti_configure
10383115Syl150051  * @hldev: HAL device handle.
10393115Syl150051  *
10403115Syl150051  * TTI Initialization.
10413115Syl150051  * Initialize Transmit Traffic Interrupt Scheme.
10423115Syl150051  */
10433115Syl150051 static xge_hal_status_e
__hal_device_tti_configure(xge_hal_device_t * hldev,int runtime)10443115Syl150051 __hal_device_tti_configure(xge_hal_device_t *hldev, int runtime)
10453115Syl150051 {
10463115Syl150051 	int i;
10473115Syl150051 
10483115Syl150051 	for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) {
10493115Syl150051 		int j;
10503115Syl150051 
10513115Syl150051 		if (!hldev->config.fifo.queue[i].configured)
10523115Syl150051 			continue;
10533115Syl150051 
10543115Syl150051 		for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) {
10553115Syl150051 			xge_hal_status_e status;
10563115Syl150051 
10573115Syl150051 			if (!hldev->config.fifo.queue[i].tti[j].enabled)
10583115Syl150051 				continue;
10593115Syl150051 
10603115Syl150051 			/* at least some TTI enabled. Record it. */
10613115Syl150051 			hldev->tti_enabled = 1;
10623115Syl150051 
10633115Syl150051 			status = __hal_device_tti_apply(hldev,
10643115Syl150051 				&hldev->config.fifo.queue[i].tti[j],
10653115Syl150051 				i * XGE_HAL_MAX_FIFO_TTI_NUM + j, runtime);
10663115Syl150051 			if (status != XGE_HAL_OK)
10673115Syl150051 				return status;
10683115Syl150051 		}
10693115Syl150051 	}
10703115Syl150051 
10713115Syl150051 	/* processing bimodal TTIs */
10723115Syl150051 	for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) {
10733115Syl150051 		xge_hal_status_e status;
10743115Syl150051 
10753115Syl150051 		if (!hldev->bimodal_tti[i].enabled)
10763115Syl150051 			continue;
10773115Syl150051 
10783115Syl150051 		/* at least some bimodal TTI enabled. Record it. */
10793115Syl150051 		hldev->tti_enabled = 1;
10803115Syl150051 
10813115Syl150051 		status = __hal_device_tti_apply(hldev, &hldev->bimodal_tti[i],
10823115Syl150051 				XGE_HAL_MAX_FIFO_TTI_RING_0 + i, runtime);
10833115Syl150051 		if (status != XGE_HAL_OK)
10843115Syl150051 			return status;
10853115Syl150051 
10863115Syl150051 	}
10873115Syl150051 
10883115Syl150051 	return XGE_HAL_OK;
10893115Syl150051 }
10903115Syl150051 
10913115Syl150051 /*
10921256Syl150051  * __hal_device_rti_configure
10931256Syl150051  * @hldev: HAL device handle.
10941256Syl150051  *
10951256Syl150051  * RTI Initialization.
10961256Syl150051  * Initialize Receive Traffic Interrupt Scheme.
10971256Syl150051  */
10983115Syl150051 xge_hal_status_e
__hal_device_rti_configure(xge_hal_device_t * hldev,int runtime)10991256Syl150051 __hal_device_rti_configure(xge_hal_device_t *hldev, int runtime)
11001256Syl150051 {
11011256Syl150051 	xge_hal_pci_bar0_t *bar0;
11021256Syl150051 	u64 val64, data1 = 0, data2 = 0;
11031256Syl150051 	int i;
11041256Syl150051 
11053115Syl150051 	if (runtime) {
11063115Syl150051 		/*
11073115Syl150051 		 * we don't want to re-configure RTI in case when
11083115Syl150051 		 * bimodal interrupts are in use. Instead reconfigure TTI
11093115Syl150051 		 * with new RTI values.
11103115Syl150051 		 */
11113115Syl150051 		if (hldev->config.bimodal_interrupts) {
11123115Syl150051 			__hal_device_bimodal_configure(hldev);
11133115Syl150051 			return __hal_device_tti_configure(hldev, 1);
11143115Syl150051 		}
11151256Syl150051 		bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
11163115Syl150051 	} else
11171256Syl150051 		bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
11181256Syl150051 
11191256Syl150051 	for (i=0; i<XGE_HAL_MAX_RING_NUM; i++) {
11201256Syl150051 		xge_hal_rti_config_t *rti = &hldev->config.ring.queue[i].rti;
11211256Syl150051 
11221256Syl150051 		if (!hldev->config.ring.queue[i].configured)
11231256Syl150051 			continue;
11241256Syl150051 
11251256Syl150051 		if (rti->timer_val_us) {
11261256Syl150051 			unsigned int rx_interval;
11271256Syl150051 
11281256Syl150051 			if (hldev->config.pci_freq_mherz) {
11291256Syl150051 				rx_interval = hldev->config.pci_freq_mherz *
11301256Syl150051 						rti->timer_val_us / 8;
11311256Syl150051 				rx_interval =
11321256Syl150051 					__hal_fix_time_ival_herc(hldev,
11331256Syl150051 								 rx_interval);
11341256Syl150051 			} else {
11351256Syl150051 				rx_interval = rti->timer_val_us;
11361256Syl150051 			}
11371256Syl150051 			data1 |=XGE_HAL_RTI_DATA1_MEM_RX_TIMER_VAL(rx_interval);
11381256Syl150051 			if (rti->timer_ac_en) {
11391256Syl150051 				data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_AC_EN;
11401256Syl150051 			}
11411256Syl150051 			data1 |= XGE_HAL_RTI_DATA1_MEM_RX_TIMER_CI_EN;
11421256Syl150051 		}
11431256Syl150051 
11441256Syl150051 		if (rti->urange_a ||
11451256Syl150051 		    rti->urange_b ||
11461256Syl150051 		    rti->urange_c ||
11471256Syl150051 		    rti->ufc_a ||
11481256Syl150051 		    rti->ufc_b ||
11491256Syl150051 		    rti->ufc_c ||
11501256Syl150051 		    rti->ufc_d) {
11511256Syl150051 			data1 |=XGE_HAL_RTI_DATA1_MEM_RX_URNG_A(rti->urange_a) |
11521256Syl150051 				XGE_HAL_RTI_DATA1_MEM_RX_URNG_B(rti->urange_b) |
11531256Syl150051 				XGE_HAL_RTI_DATA1_MEM_RX_URNG_C(rti->urange_c);
11541256Syl150051 
11551256Syl150051 			data2 |= XGE_HAL_RTI_DATA2_MEM_RX_UFC_A(rti->ufc_a) |
11561256Syl150051 				 XGE_HAL_RTI_DATA2_MEM_RX_UFC_B(rti->ufc_b) |
11571256Syl150051 				 XGE_HAL_RTI_DATA2_MEM_RX_UFC_C(rti->ufc_c) |
11581256Syl150051 				 XGE_HAL_RTI_DATA2_MEM_RX_UFC_D(rti->ufc_d);
11591256Syl150051 		}
11601256Syl150051 
11616937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
11626937Sxw161283 		    data1, &bar0->rti_data1_mem);
11636937Sxw161283 		(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
11646937Sxw161283 		    &bar0->rti_data1_mem);
11656937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
11666937Sxw161283 		    data2, &bar0->rti_data2_mem);
11676937Sxw161283 		(void)xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
11686937Sxw161283 		    &bar0->rti_data2_mem);
11696937Sxw161283 
11701256Syl150051 		xge_os_wmb();
11711256Syl150051 
11721256Syl150051 		val64 = XGE_HAL_RTI_CMD_MEM_WE |
11731256Syl150051 		XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD;
11741256Syl150051 		val64 |= XGE_HAL_RTI_CMD_MEM_OFFSET(i);
11751256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
11761256Syl150051 		                    &bar0->rti_command_mem);
11771256Syl150051 
11781256Syl150051 		if (!runtime && __hal_device_register_poll(hldev,
11791256Syl150051 			&bar0->rti_command_mem, 0,
11801256Syl150051 			XGE_HAL_RTI_CMD_MEM_STROBE_NEW_CMD,
11811256Syl150051 			XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
11821256Syl150051 			/* upper layer may require to repeat */
11831256Syl150051 			return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
11841256Syl150051 		}
11853115Syl150051 
11863115Syl150051 		if (!runtime) {
11873115Syl150051 			xge_debug_device(XGE_TRACE,
11883115Syl150051 			  "RTI[%d] configured: rti_data1_mem 0x"XGE_OS_LLXFMT,
11893115Syl150051 			  i,
11903115Syl150051 			  (unsigned long long)xge_os_pio_mem_read64(hldev->pdev,
11913115Syl150051 					  hldev->regh0, &bar0->rti_data1_mem));
11921256Syl150051 		}
11933115Syl150051 	}
11941256Syl150051 
11951256Syl150051 	return XGE_HAL_OK;
11961256Syl150051 }
11971256Syl150051 
11981256Syl150051 
11991256Syl150051 /* Constants to be programmed into the Xena's registers to configure
12001256Syl150051  * the XAUI. */
12011256Syl150051 static u64 default_xena_mdio_cfg[] = {
12021256Syl150051 	/* Reset PMA PLL */
12031256Syl150051 	0xC001010000000000ULL, 0xC0010100000000E0ULL,
12041256Syl150051 	0xC0010100008000E4ULL,
12051256Syl150051 	/* Remove Reset from PMA PLL */
12061256Syl150051 	0xC001010000000000ULL, 0xC0010100000000E0ULL,
12071256Syl150051 	0xC0010100000000E4ULL,
12081256Syl150051 	END_SIGN
12091256Syl150051 };
12101256Syl150051 
12111256Syl150051 static u64 default_herc_mdio_cfg[] = {
12121256Syl150051 	END_SIGN
12131256Syl150051 };
12141256Syl150051 
12151256Syl150051 static u64 default_xena_dtx_cfg[] = {
12161256Syl150051 	0x8000051500000000ULL, 0x80000515000000E0ULL,
12171256Syl150051 	0x80000515D93500E4ULL, 0x8001051500000000ULL,
12181256Syl150051 	0x80010515000000E0ULL, 0x80010515001E00E4ULL,
12191256Syl150051 	0x8002051500000000ULL, 0x80020515000000E0ULL,
12201256Syl150051 	0x80020515F21000E4ULL,
12211256Syl150051 	/* Set PADLOOPBACKN */
12221256Syl150051 	0x8002051500000000ULL, 0x80020515000000E0ULL,
12231256Syl150051 	0x80020515B20000E4ULL, 0x8003051500000000ULL,
12241256Syl150051 	0x80030515000000E0ULL, 0x80030515B20000E4ULL,
12251256Syl150051 	0x8004051500000000ULL, 0x80040515000000E0ULL,
12261256Syl150051 	0x80040515B20000E4ULL, 0x8005051500000000ULL,
12271256Syl150051 	0x80050515000000E0ULL, 0x80050515B20000E4ULL,
12281256Syl150051 	SWITCH_SIGN,
12291256Syl150051 	/* Remove PADLOOPBACKN */
12301256Syl150051 	0x8002051500000000ULL, 0x80020515000000E0ULL,
12311256Syl150051 	0x80020515F20000E4ULL, 0x8003051500000000ULL,
12321256Syl150051 	0x80030515000000E0ULL, 0x80030515F20000E4ULL,
12331256Syl150051 	0x8004051500000000ULL, 0x80040515000000E0ULL,
12341256Syl150051 	0x80040515F20000E4ULL, 0x8005051500000000ULL,
12351256Syl150051 	0x80050515000000E0ULL, 0x80050515F20000E4ULL,
12361256Syl150051 	END_SIGN
12371256Syl150051 };
12381256Syl150051 
12391256Syl150051 /*
12401256Syl150051 static u64 default_herc_dtx_cfg[] = {
12411256Syl150051 	0x80000515BA750000ULL, 0x80000515BA7500E0ULL,
12421256Syl150051 	0x80000515BA750004ULL, 0x80000515BA7500E4ULL,
12431256Syl150051 	0x80010515003F0000ULL, 0x80010515003F00E0ULL,
12441256Syl150051 	0x80010515003F0004ULL, 0x80010515003F00E4ULL,
12451256Syl150051 	0x80020515F2100000ULL, 0x80020515F21000E0ULL,
12461256Syl150051 	0x80020515F2100004ULL, 0x80020515F21000E4ULL,
12471256Syl150051 	END_SIGN
12481256Syl150051 };
12491256Syl150051 */
12501256Syl150051 
12511256Syl150051 static u64 default_herc_dtx_cfg[] = {
12521256Syl150051     0x8000051536750000ULL, 0x80000515367500E0ULL,
12531256Syl150051     0x8000051536750004ULL, 0x80000515367500E4ULL,
12541256Syl150051 
12551256Syl150051     0x80010515003F0000ULL, 0x80010515003F00E0ULL,
12561256Syl150051     0x80010515003F0004ULL, 0x80010515003F00E4ULL,
12571256Syl150051 
12581256Syl150051     0x801205150D440000ULL, 0x801205150D4400E0ULL,
12591256Syl150051     0x801205150D440004ULL, 0x801205150D4400E4ULL,
12601256Syl150051 
12611256Syl150051     0x80020515F2100000ULL, 0x80020515F21000E0ULL,
12621256Syl150051     0x80020515F2100004ULL, 0x80020515F21000E4ULL,
12631256Syl150051     END_SIGN
12641256Syl150051 };
12651256Syl150051 
12666937Sxw161283 
12676937Sxw161283 void
__hal_serial_mem_write64(xge_hal_device_t * hldev,u64 value,u64 * reg)12686937Sxw161283 __hal_serial_mem_write64(xge_hal_device_t *hldev, u64 value, u64 *reg)
12696937Sxw161283 {
12706937Sxw161283 	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
12716937Sxw161283 		    (u32)(value>>32), reg);
12726937Sxw161283 	xge_os_wmb();
12736937Sxw161283 	__hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0,
12746937Sxw161283 		    (u32)value, reg);
12756937Sxw161283 	xge_os_wmb();
12766937Sxw161283 	xge_os_mdelay(1);
12776937Sxw161283 }
12786937Sxw161283 
12796937Sxw161283 u64
__hal_serial_mem_read64(xge_hal_device_t * hldev,u64 * reg)12806937Sxw161283 __hal_serial_mem_read64(xge_hal_device_t *hldev, u64 *reg)
12816937Sxw161283 {
12826937Sxw161283 	u64 val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
12836937Sxw161283 			reg);
12846937Sxw161283 	xge_os_mdelay(1);
12856937Sxw161283 	return val64;
12866937Sxw161283 }
12876937Sxw161283 
12881256Syl150051 /*
12891256Syl150051  * __hal_device_xaui_configure
12901256Syl150051  * @hldev: HAL device handle.
12911256Syl150051  *
12921256Syl150051  * Configure XAUI Interface of Xena.
12931256Syl150051  *
12941256Syl150051  * To Configure the Xena's XAUI, one has to write a series
12951256Syl150051  * of 64 bit values into two registers in a particular
12961256Syl150051  * sequence. Hence a macro 'SWITCH_SIGN' has been defined
12971256Syl150051  * which will be defined in the array of configuration values
12981256Syl150051  * (default_dtx_cfg & default_mdio_cfg) at appropriate places
12991256Syl150051  * to switch writing from one regsiter to another. We continue
13001256Syl150051  * writing these values until we encounter the 'END_SIGN' macro.
13011256Syl150051  * For example, After making a series of 21 writes into
13021256Syl150051  * dtx_control register the 'SWITCH_SIGN' appears and hence we
13031256Syl150051  * start writing into mdio_control until we encounter END_SIGN.
13041256Syl150051  */
13051256Syl150051 static void
__hal_device_xaui_configure(xge_hal_device_t * hldev)13061256Syl150051 __hal_device_xaui_configure(xge_hal_device_t *hldev)
13071256Syl150051 {
13081256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
13091256Syl150051 	int mdio_cnt = 0, dtx_cnt = 0;
13101256Syl150051 	u64 *default_dtx_cfg = NULL, *default_mdio_cfg = NULL;
13111256Syl150051 
13121256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) {
13131256Syl150051 		default_dtx_cfg = default_xena_dtx_cfg;
13141256Syl150051 		default_mdio_cfg = default_xena_mdio_cfg;
13151256Syl150051 	} else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
13161256Syl150051 		default_dtx_cfg = default_herc_dtx_cfg;
13171256Syl150051 		default_mdio_cfg = default_herc_mdio_cfg;
13186937Sxw161283 	} else {
13193115Syl150051 		xge_assert(default_dtx_cfg);
13206937Sxw161283     return;
13216937Sxw161283   }
13221256Syl150051 
13231256Syl150051 	do {
13241256Syl150051 	    dtx_cfg:
13251256Syl150051 		while (default_dtx_cfg[dtx_cnt] != END_SIGN) {
13261256Syl150051 			if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
13271256Syl150051 				dtx_cnt++;
13281256Syl150051 				goto mdio_cfg;
13291256Syl150051 			}
13306937Sxw161283 			__hal_serial_mem_write64(hldev, default_dtx_cfg[dtx_cnt],
13316937Sxw161283 					       &bar0->dtx_control);
13321256Syl150051 			dtx_cnt++;
13331256Syl150051 		}
13341256Syl150051 	    mdio_cfg:
13351256Syl150051 		while (default_mdio_cfg[mdio_cnt] != END_SIGN) {
13361256Syl150051 			if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
13371256Syl150051 				mdio_cnt++;
13381256Syl150051 				goto dtx_cfg;
13391256Syl150051 			}
13406937Sxw161283 			__hal_serial_mem_write64(hldev, default_mdio_cfg[mdio_cnt],
13416937Sxw161283 				&bar0->mdio_control);
13421256Syl150051 			mdio_cnt++;
13431256Syl150051 		}
13441256Syl150051 	} while ( !((default_dtx_cfg[dtx_cnt] == END_SIGN) &&
13451256Syl150051 		    (default_mdio_cfg[mdio_cnt] == END_SIGN)) );
13461256Syl150051 
13471256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "XAUI interface configured");
13481256Syl150051 }
13491256Syl150051 
13501256Syl150051 /*
13511256Syl150051  * __hal_device_mac_link_util_set
13521256Syl150051  * @hldev: HAL device handle.
13531256Syl150051  *
13541256Syl150051  * Set sampling rate to calculate link utilization.
13551256Syl150051  */
13561256Syl150051 static void
__hal_device_mac_link_util_set(xge_hal_device_t * hldev)13571256Syl150051 __hal_device_mac_link_util_set(xge_hal_device_t *hldev)
13581256Syl150051 {
13591256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
13601256Syl150051 	u64 val64;
13611256Syl150051 
13621256Syl150051 	val64 = XGE_HAL_MAC_TX_LINK_UTIL_VAL(
13631256Syl150051 			hldev->config.mac.tmac_util_period) |
13641256Syl150051 		XGE_HAL_MAC_RX_LINK_UTIL_VAL(
13651256Syl150051 			hldev->config.mac.rmac_util_period);
13661256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
13671256Syl150051 	                     &bar0->mac_link_util);
13681256Syl150051 	xge_debug_device(XGE_TRACE, "%s",
13691256Syl150051 			  "bandwidth link utilization configured");
13701256Syl150051 }
13711256Syl150051 
13721256Syl150051 /*
13731256Syl150051  * __hal_device_set_swapper
13741256Syl150051  * @hldev: HAL device handle.
13751256Syl150051  *
13761256Syl150051  * Set the Xframe's byte "swapper" in accordance with
13771256Syl150051  * endianness of the host.
13781256Syl150051  */
13791256Syl150051 xge_hal_status_e
__hal_device_set_swapper(xge_hal_device_t * hldev)13801256Syl150051 __hal_device_set_swapper(xge_hal_device_t *hldev)
13811256Syl150051 {
13821256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
13831256Syl150051 	u64 val64;
13841256Syl150051 
13851256Syl150051 	/*
13861256Syl150051 	 * from 32bit errarta:
13871256Syl150051 	 *
13881256Syl150051 	 * The SWAPPER_CONTROL register determines how the adapter accesses
13891256Syl150051 	 * host memory as well as how it responds to read and write requests
13901256Syl150051 	 * from the host system. Writes to this register should be performed
13911256Syl150051 	 * carefully, since the byte swappers could reverse the order of bytes.
13921256Syl150051 	 * When configuring this register keep in mind that writes to the PIF
13931256Syl150051 	 * read and write swappers could reverse the order of the upper and
13941256Syl150051 	 * lower 32-bit words. This means that the driver may have to write
13951256Syl150051 	 * to the upper 32 bits of the SWAPPER_CONTROL twice in order to
13961256Syl150051 	 * configure the entire register. */
13971256Syl150051 
13981256Syl150051 	/*
13991256Syl150051 	 * The device by default set to a big endian format, so a big endian
14001256Syl150051 	 * driver need not set anything.
14011256Syl150051 	 */
14021256Syl150051 
14031256Syl150051 #if defined(XGE_HAL_CUSTOM_HW_SWAPPER)
14041256Syl150051 
14051256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
14061256Syl150051 			0xffffffffffffffffULL, &bar0->swapper_ctrl);
14071256Syl150051 
14081256Syl150051 	val64 = XGE_HAL_CUSTOM_HW_SWAPPER;
14091256Syl150051 
14101256Syl150051 	xge_os_wmb();
14111256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
14121256Syl150051 			     &bar0->swapper_ctrl);
14131256Syl150051 
14143115Syl150051 	xge_debug_device(XGE_TRACE, "using custom HW swapper 0x"XGE_OS_LLXFMT,
14151256Syl150051 			(unsigned long long)val64);
14161256Syl150051 
14171256Syl150051 #elif !defined(XGE_OS_HOST_BIG_ENDIAN)
14181256Syl150051 
14191256Syl150051 	/*
14201256Syl150051 	 * Initially we enable all bits to make it accessible by the driver,
14211256Syl150051 	 * then we selectively enable only those bits that we want to set.
14221256Syl150051 	 * i.e. force swapper to swap for the first time since second write
14231256Syl150051 	 * will overwrite with the final settings.
14241256Syl150051 	 *
14251256Syl150051 	 * Use only for little endian platforms.
14261256Syl150051 	 */
14271256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
14281256Syl150051 			0xffffffffffffffffULL, &bar0->swapper_ctrl);
14291256Syl150051 	xge_os_wmb();
14301256Syl150051 	val64 = (XGE_HAL_SWAPPER_CTRL_PIF_R_FE |
14311256Syl150051 		 XGE_HAL_SWAPPER_CTRL_PIF_R_SE |
14321256Syl150051 		 XGE_HAL_SWAPPER_CTRL_PIF_W_FE |
14331256Syl150051 		 XGE_HAL_SWAPPER_CTRL_PIF_W_SE |
14341256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RTH_FE |
14351256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RTH_SE |
14361256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXP_FE |
14371256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXP_SE |
14381256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXD_R_FE |
14391256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXD_R_SE |
14401256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXD_W_FE |
14411256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXD_W_SE |
14421256Syl150051 		 XGE_HAL_SWAPPER_CTRL_TXF_R_FE |
14431256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RXD_R_FE |
14441256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RXD_R_SE |
14451256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RXD_W_FE |
14461256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RXD_W_SE |
14471256Syl150051 		 XGE_HAL_SWAPPER_CTRL_RXF_W_FE |
14481256Syl150051 		 XGE_HAL_SWAPPER_CTRL_XMSI_FE |
14491256Syl150051 		 XGE_HAL_SWAPPER_CTRL_STATS_FE | XGE_HAL_SWAPPER_CTRL_STATS_SE);
14506937Sxw161283 
14516937Sxw161283 	/*
14521256Syl150051 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) {
14531256Syl150051 		 val64 |= XGE_HAL_SWAPPER_CTRL_XMSI_SE;
14541256Syl150051 	} */
14551256Syl150051 	__hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0, (u32)val64,
14561256Syl150051 	                     &bar0->swapper_ctrl);
14571256Syl150051 	xge_os_wmb();
14581256Syl150051 	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32),
14591256Syl150051 	                     &bar0->swapper_ctrl);
14601256Syl150051 	xge_os_wmb();
14611256Syl150051 	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64>>32),
14621256Syl150051 	                     &bar0->swapper_ctrl);
14631256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "using little endian set");
14641256Syl150051 #endif
14651256Syl150051 
14661256Syl150051 	/*  Verifying if endian settings are accurate by reading a feedback
14671256Syl150051 	 *  register.  */
14681256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
14691256Syl150051 	                            &bar0->pif_rd_swapper_fb);
14701256Syl150051 	if (val64 != XGE_HAL_IF_RD_SWAPPER_FB) {
14713115Syl150051 		xge_debug_device(XGE_ERR, "pif_rd_swapper_fb read "XGE_OS_LLXFMT,
14721256Syl150051 			  (unsigned long long) val64);
14731256Syl150051 		return XGE_HAL_ERR_SWAPPER_CTRL;
14741256Syl150051 	}
14751256Syl150051 
14761256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "be/le swapper enabled");
14771256Syl150051 
14781256Syl150051 	return XGE_HAL_OK;
14791256Syl150051 }
14801256Syl150051 
14811256Syl150051 /*
14821256Syl150051  * __hal_device_rts_mac_configure - Configure RTS steering based on
14831256Syl150051  * destination mac address.
14841256Syl150051  * @hldev: HAL device handle.
14851256Syl150051  *
14861256Syl150051  */
14871256Syl150051 xge_hal_status_e
__hal_device_rts_mac_configure(xge_hal_device_t * hldev)14881256Syl150051 __hal_device_rts_mac_configure(xge_hal_device_t *hldev)
14891256Syl150051 {
14901256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
14911256Syl150051 	u64 val64;
14921256Syl150051 
14931256Syl150051 	if (!hldev->config.rts_mac_en) {
14941256Syl150051 		return XGE_HAL_OK;
14951256Syl150051 	}
14961256Syl150051 
14971256Syl150051 	/*
14981256Syl150051 	* Set the receive traffic steering mode from default(classic)
14991256Syl150051 	* to enhanced.
15001256Syl150051 	*/
15011256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
15021256Syl150051 					&bar0->rts_ctrl);
15031256Syl150051 	val64 |=  XGE_HAL_RTS_CTRL_ENHANCED_MODE;
15041256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
15051256Syl150051 				val64, &bar0->rts_ctrl);
15061256Syl150051 	return XGE_HAL_OK;
15071256Syl150051 }
15081256Syl150051 
15091256Syl150051 /*
15106937Sxw161283  * __hal_device_rts_port_configure - Configure RTS steering based on
15116937Sxw161283  * destination or source port number.
15126937Sxw161283  * @hldev: HAL device handle.
15136937Sxw161283  *
15146937Sxw161283  */
15156937Sxw161283 xge_hal_status_e
__hal_device_rts_port_configure(xge_hal_device_t * hldev)15166937Sxw161283 __hal_device_rts_port_configure(xge_hal_device_t *hldev)
15176937Sxw161283 {
15186937Sxw161283 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
15196937Sxw161283 	u64 val64;
15206937Sxw161283 	int rnum;
15216937Sxw161283 
15226937Sxw161283 	if (!hldev->config.rts_port_en) {
15236937Sxw161283 		return XGE_HAL_OK;
15246937Sxw161283 	}
15256937Sxw161283 
15266937Sxw161283 	/*
15276937Sxw161283 	 * Set the receive traffic steering mode from default(classic)
15286937Sxw161283 	 * to enhanced.
15296937Sxw161283 	 */
15306937Sxw161283 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
15316937Sxw161283 					&bar0->rts_ctrl);
15326937Sxw161283 	val64 |=  XGE_HAL_RTS_CTRL_ENHANCED_MODE;
15336937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
15346937Sxw161283 				val64, &bar0->rts_ctrl);
15356937Sxw161283 
15366937Sxw161283 	/*
15376937Sxw161283 	 * Initiate port steering according to per-ring configuration
15386937Sxw161283 	 */
15396937Sxw161283 	for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) {
15406937Sxw161283 		int pnum;
15416937Sxw161283 		xge_hal_ring_queue_t *queue = &hldev->config.ring.queue[rnum];
15426937Sxw161283 
15436937Sxw161283 		if (!queue->configured || queue->rts_port_en)
15446937Sxw161283 			continue;
15456937Sxw161283 
15466937Sxw161283 		for (pnum = 0; pnum < XGE_HAL_MAX_STEERABLE_PORTS; pnum++) {
15476937Sxw161283 			xge_hal_rts_port_t *port = &queue->rts_ports[pnum];
15486937Sxw161283 
15496937Sxw161283 			/*
15506937Sxw161283 			 * Skip and clear empty ports
15516937Sxw161283 			 */
15526937Sxw161283 			if (!port->num) {
15536937Sxw161283 				/*
15546937Sxw161283 				 * Clear CAM memory
15556937Sxw161283 				 */
15566937Sxw161283 				xge_os_pio_mem_write64(hldev->pdev,
15576937Sxw161283 				       hldev->regh0, 0ULL,
15586937Sxw161283 				       &bar0->rts_pn_cam_data);
15596937Sxw161283 
15606937Sxw161283 				val64 = BIT(7) | BIT(15);
15616937Sxw161283 			} else {
15626937Sxw161283 				/*
15636937Sxw161283 				 * Assign new Port values according
15646937Sxw161283 				 * to configuration
15656937Sxw161283 				 */
15666937Sxw161283 				val64 = vBIT(port->num,8,16) |
15676937Sxw161283 					vBIT(rnum,37,3) | BIT(63);
15686937Sxw161283 				if (port->src)
15696937Sxw161283 					val64 = BIT(47);
15706937Sxw161283 				if (!port->udp)
15716937Sxw161283 					val64 = BIT(7);
15726937Sxw161283 				xge_os_pio_mem_write64(hldev->pdev,
15736937Sxw161283 					       hldev->regh0, val64,
15746937Sxw161283 					       &bar0->rts_pn_cam_data);
15756937Sxw161283 
15766937Sxw161283 				val64 = BIT(7) | BIT(15) | vBIT(pnum,24,8);
15776937Sxw161283 			}
15786937Sxw161283 
15796937Sxw161283 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
15806937Sxw161283 					       val64, &bar0->rts_pn_cam_ctrl);
15816937Sxw161283 
15826937Sxw161283 			/* poll until done */
15836937Sxw161283 			if (__hal_device_register_poll(hldev,
15846937Sxw161283 			       &bar0->rts_pn_cam_ctrl, 0,
15856937Sxw161283 			       XGE_HAL_RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED,
15866937Sxw161283 			       XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) !=
15876937Sxw161283 								XGE_HAL_OK) {
15886937Sxw161283 				/* upper layer may require to repeat */
15896937Sxw161283 				return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
15906937Sxw161283 			}
15916937Sxw161283 		}
15926937Sxw161283 	}
15936937Sxw161283 	return XGE_HAL_OK;
15946937Sxw161283 }
15956937Sxw161283 
15966937Sxw161283 /*
15973115Syl150051  * __hal_device_rts_qos_configure - Configure RTS steering based on
15983115Syl150051  * qos.
15993115Syl150051  * @hldev: HAL device handle.
16003115Syl150051  *
16013115Syl150051  */
16023115Syl150051 xge_hal_status_e
__hal_device_rts_qos_configure(xge_hal_device_t * hldev)16033115Syl150051 __hal_device_rts_qos_configure(xge_hal_device_t *hldev)
16043115Syl150051 {
16053115Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
16063115Syl150051 	u64 val64;
16076937Sxw161283 	int j, rx_ring_num;
16086937Sxw161283 
16096937Sxw161283 	if (!hldev->config.rts_qos_en) {
16103115Syl150051 		return XGE_HAL_OK;
16113115Syl150051 	}
16123115Syl150051 
16136937Sxw161283 	/* First clear the RTS_DS_MEM_DATA */
16146937Sxw161283 	val64 = 0;
16156937Sxw161283 	for (j = 0; j < 64; j++ )
16166937Sxw161283 	{
16176937Sxw161283 		/* First clear the value */
16186937Sxw161283 		val64 = XGE_HAL_RTS_DS_MEM_DATA(0);
16196937Sxw161283 
16206937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
16216937Sxw161283 				       &bar0->rts_ds_mem_data);
16226937Sxw161283 
16236937Sxw161283 		val64 = XGE_HAL_RTS_DS_MEM_CTRL_WE |
16246937Sxw161283 			XGE_HAL_RTS_DS_MEM_CTRL_STROBE_NEW_CMD |
16256937Sxw161283 			XGE_HAL_RTS_DS_MEM_CTRL_OFFSET ( j );
16266937Sxw161283 
16276937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
16286937Sxw161283 				       &bar0->rts_ds_mem_ctrl);
16293115Syl150051 
16303115Syl150051 
16313115Syl150051 		/* poll until done */
16323115Syl150051 		if (__hal_device_register_poll(hldev,
16333115Syl150051 		       &bar0->rts_ds_mem_ctrl, 0,
16343115Syl150051 		       XGE_HAL_RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED,
16353115Syl150051 		       XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
16363115Syl150051 			/* upper layer may require to repeat */
16373115Syl150051 			return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
16383115Syl150051 		}
16393115Syl150051 
16406937Sxw161283 	}
16416937Sxw161283 
16426937Sxw161283 	rx_ring_num = 0;
16436937Sxw161283 	for (j = 0; j < XGE_HAL_MAX_RING_NUM; j++) {
16446937Sxw161283 		if (hldev->config.ring.queue[j].configured)
16456937Sxw161283 			rx_ring_num++;
16466937Sxw161283 	}
16476937Sxw161283 
16486937Sxw161283 	switch (rx_ring_num) {
16496937Sxw161283 	case 1:
16506937Sxw161283 		val64 = 0x0;
16516937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
16526937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
16536937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
16546937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
16556937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
16566937Sxw161283 		break;
16576937Sxw161283 	case 2:
16586937Sxw161283 		val64 = 0x0001000100010001ULL;
16596937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
16606937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
16616937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
16626937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
16636937Sxw161283 		val64 = 0x0001000100000000ULL;
16646937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
16656937Sxw161283 		break;
16666937Sxw161283 	case 3:
16676937Sxw161283 		val64 = 0x0001020001020001ULL;
16686937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
16696937Sxw161283 		val64 = 0x0200010200010200ULL;
16706937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
16716937Sxw161283 		val64 = 0x0102000102000102ULL;
16726937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
16736937Sxw161283 		val64 = 0x0001020001020001ULL;
16746937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
16756937Sxw161283 		val64 = 0x0200010200000000ULL;
16766937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
16776937Sxw161283 		break;
16786937Sxw161283 	case 4:
16796937Sxw161283 		val64 = 0x0001020300010203ULL;
16806937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
16816937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
16826937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
16836937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
16846937Sxw161283 		val64 = 0x0001020300000000ULL;
16856937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
16866937Sxw161283 		break;
16876937Sxw161283 	case 5:
16886937Sxw161283 		val64 = 0x0001020304000102ULL;
16896937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
16906937Sxw161283 		val64 = 0x0304000102030400ULL;
16916937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
16926937Sxw161283 		val64 = 0x0102030400010203ULL;
16936937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
16946937Sxw161283 		val64 = 0x0400010203040001ULL;
16956937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
16966937Sxw161283 		val64 = 0x0203040000000000ULL;
16976937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
16986937Sxw161283 		break;
16996937Sxw161283 	case 6:
17006937Sxw161283 		val64 = 0x0001020304050001ULL;
17016937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
17026937Sxw161283 		val64 = 0x0203040500010203ULL;
17036937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
17046937Sxw161283 		val64 = 0x0405000102030405ULL;
17056937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
17066937Sxw161283 		val64 = 0x0001020304050001ULL;
17076937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
17086937Sxw161283 		val64 = 0x0203040500000000ULL;
17096937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
17106937Sxw161283 		break;
17116937Sxw161283 	case 7:
17126937Sxw161283 		val64 = 0x0001020304050600ULL;
17136937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
17146937Sxw161283 		val64 = 0x0102030405060001ULL;
17156937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
17166937Sxw161283 		val64 = 0x0203040506000102ULL;
17176937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
17186937Sxw161283 		val64 = 0x0304050600010203ULL;
17196937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
17206937Sxw161283 		val64 = 0x0405060000000000ULL;
17216937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
17226937Sxw161283 		break;
17236937Sxw161283 	case 8:
17246937Sxw161283 		val64 = 0x0001020304050607ULL;
17256937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_0);
17266937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_1);
17276937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_2);
17286937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_3);
17296937Sxw161283 		val64 = 0x0001020300000000ULL;
17306937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rx_w_round_robin_4);
17316937Sxw161283 		break;
17326937Sxw161283 	}
17336937Sxw161283 
17343115Syl150051 	return XGE_HAL_OK;
17353115Syl150051 }
17363115Syl150051 
17373115Syl150051 /*
17381256Syl150051  * xge__hal_device_rts_mac_enable
17391256Syl150051  *
17401256Syl150051  * @devh: HAL device handle.
17411256Syl150051  * @index: index number where the MAC addr will be stored
17421256Syl150051  * @macaddr: MAC address
17431256Syl150051  *
17441256Syl150051  * - Enable RTS steering for the given MAC address. This function has to be
17451256Syl150051  * called with lock acquired.
17461256Syl150051  *
17471256Syl150051  * NOTE:
17481256Syl150051  * 1. ULD has to call this function with the index value which
17491256Syl150051  *    statisfies the following condition:
17501256Syl150051  *	ring_num = (index % 8)
17511256Syl150051  * 2.ULD also needs to make sure that the index is not
17521256Syl150051  *   occupied by any MAC address. If that index has any MAC address
17531256Syl150051  *   it will be overwritten and HAL will not check for it.
17541256Syl150051  *
17551256Syl150051  */
17561256Syl150051 xge_hal_status_e
xge_hal_device_rts_mac_enable(xge_hal_device_h devh,int index,macaddr_t macaddr)17571256Syl150051 xge_hal_device_rts_mac_enable(xge_hal_device_h devh, int index, macaddr_t macaddr)
17581256Syl150051 {
17593115Syl150051 	int max_addr = XGE_HAL_MAX_MAC_ADDRESSES;
17601256Syl150051 	xge_hal_status_e status;
17611256Syl150051 
17621256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
17633115Syl150051 
17643115Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
17653115Syl150051 		max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC;
17663115Syl150051 
17673115Syl150051 	if ( index >= max_addr )
17681256Syl150051 		return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES;
17691256Syl150051 
17701256Syl150051 	/*
17711256Syl150051 	 * Set the MAC address at the given location marked by index.
17721256Syl150051 	 */
17731256Syl150051 	status = xge_hal_device_macaddr_set(hldev, index, macaddr);
17741256Syl150051 	if (status != XGE_HAL_OK) {
17751256Syl150051 		xge_debug_device(XGE_ERR, "%s",
17761256Syl150051 			"Not able to set the mac addr");
17771256Syl150051 		return status;
17781256Syl150051 	}
17791256Syl150051 
17803115Syl150051 	return xge_hal_device_rts_section_enable(hldev, index);
17811256Syl150051 }
17821256Syl150051 
17831256Syl150051 /*
17841256Syl150051  * xge__hal_device_rts_mac_disable
17851256Syl150051  * @hldev: HAL device handle.
17861256Syl150051  * @index: index number where to disable the MAC addr
17871256Syl150051  *
17881256Syl150051  * Disable RTS Steering based on the MAC address.
17891256Syl150051  * This function should be called with lock acquired.
17901256Syl150051  *
17911256Syl150051  */
17921256Syl150051 xge_hal_status_e
xge_hal_device_rts_mac_disable(xge_hal_device_h devh,int index)17931256Syl150051 xge_hal_device_rts_mac_disable(xge_hal_device_h devh, int index)
17941256Syl150051 {
17951256Syl150051 	xge_hal_status_e status;
17961256Syl150051 	u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
17973115Syl150051 	int max_addr = XGE_HAL_MAX_MAC_ADDRESSES;
17981256Syl150051 
17991256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
18001256Syl150051 
18016937Sxw161283 	xge_debug_ll(XGE_TRACE, "the index value is %d ", index);
18023115Syl150051 
18033115Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
18043115Syl150051 		max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC;
18053115Syl150051 
18063115Syl150051 	if ( index >= max_addr )
18071256Syl150051 		return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES;
18081256Syl150051 
18091256Syl150051 	/*
18101256Syl150051 	 * Disable MAC address @ given index location
18111256Syl150051 	 */
18121256Syl150051 	status = xge_hal_device_macaddr_set(hldev, index, macaddr);
18131256Syl150051 	if (status != XGE_HAL_OK) {
18141256Syl150051 		xge_debug_device(XGE_ERR, "%s",
18151256Syl150051 			"Not able to set the mac addr");
18161256Syl150051 		return status;
18171256Syl150051 	}
18181256Syl150051 
18191256Syl150051 	return XGE_HAL_OK;
18201256Syl150051 }
18211256Syl150051 
18221256Syl150051 
18231256Syl150051 /*
18241256Syl150051  * __hal_device_rth_configure - Configure RTH for the device
18251256Syl150051  * @hldev: HAL device handle.
18261256Syl150051  *
18271256Syl150051  * Using IT (Indirection Table).
18281256Syl150051  */
18291256Syl150051 xge_hal_status_e
__hal_device_rth_it_configure(xge_hal_device_t * hldev)18301256Syl150051 __hal_device_rth_it_configure(xge_hal_device_t *hldev)
18311256Syl150051 {
18321256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
18331256Syl150051 	u64 val64;
18341256Syl150051 	int rings[XGE_HAL_MAX_RING_NUM]={0};
18351256Syl150051 	int rnum;
18361256Syl150051 	int rmax;
18371256Syl150051 	int buckets_num;
18381256Syl150051 	int bucket;
18391256Syl150051 
18401256Syl150051 	if (!hldev->config.rth_en) {
18411256Syl150051 		return XGE_HAL_OK;
18421256Syl150051 	}
18431256Syl150051 
18441256Syl150051 	/*
18451256Syl150051 	 * Set the receive traffic steering mode from default(classic)
18461256Syl150051 	 * to enhanced.
18471256Syl150051 	 */
18481256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
18491256Syl150051 				      &bar0->rts_ctrl);
18501256Syl150051 	val64 |=  XGE_HAL_RTS_CTRL_ENHANCED_MODE;
18511256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
18521256Syl150051 			       val64, &bar0->rts_ctrl);
18531256Syl150051 
18541256Syl150051 	buckets_num = (1 << hldev->config.rth_bucket_size);
18551256Syl150051 
18561256Syl150051 	rmax=0;
18571256Syl150051 	for (rnum = 0; rnum < XGE_HAL_MAX_RING_NUM; rnum++) {
18581256Syl150051 		if (hldev->config.ring.queue[rnum].configured &&
18591256Syl150051 				hldev->config.ring.queue[rnum].rth_en)
18601256Syl150051 				rings[rmax++] = rnum;
18616937Sxw161283 	}
18621256Syl150051 
18631256Syl150051 	rnum = 0;
18641256Syl150051 	/* for starters: fill in all the buckets with rings "equally" */
18651256Syl150051 	for (bucket = 0; bucket < buckets_num; bucket++) {
18661256Syl150051 
18671256Syl150051 	    if (rnum == rmax)
18681256Syl150051            rnum = 0;
18691256Syl150051 
18701256Syl150051 		/* write data */
18711256Syl150051 		val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN |
18721256Syl150051 		        XGE_HAL_RTS_RTH_MAP_MEM_DATA(rings[rnum]);
18731256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
18741256Syl150051 				     &bar0->rts_rth_map_mem_data);
18751256Syl150051 
18761256Syl150051 		/* execute */
18771256Syl150051 		val64 = XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE |
18781256Syl150051 			XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE |
18791256Syl150051 			XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(bucket);
18801256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
18811256Syl150051 				     &bar0->rts_rth_map_mem_ctrl);
18821256Syl150051 
18831256Syl150051 		/* poll until done */
18841256Syl150051 		if (__hal_device_register_poll(hldev,
18851256Syl150051 			&bar0->rts_rth_map_mem_ctrl, 0,
18861256Syl150051 			XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE,
18871256Syl150051 			XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
18881256Syl150051 			return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
18891256Syl150051 		}
18901256Syl150051 
18911256Syl150051         rnum++;
18921256Syl150051 	}
18931256Syl150051 
18941256Syl150051 	val64 = XGE_HAL_RTS_RTH_EN;
18951256Syl150051 	val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(hldev->config.rth_bucket_size);
18966937Sxw161283 	val64 |= XGE_HAL_RTS_RTH_TCP_IPV4_EN | XGE_HAL_RTS_RTH_UDP_IPV4_EN | XGE_HAL_RTS_RTH_IPV4_EN |
18971256Syl150051 			 XGE_HAL_RTS_RTH_TCP_IPV6_EN |XGE_HAL_RTS_RTH_UDP_IPV6_EN | XGE_HAL_RTS_RTH_IPV6_EN |
18981256Syl150051 			 XGE_HAL_RTS_RTH_TCP_IPV6_EX_EN | XGE_HAL_RTS_RTH_UDP_IPV6_EX_EN | XGE_HAL_RTS_RTH_IPV6_EX_EN;
18991256Syl150051 
19001256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
19011256Syl150051 			     &bar0->rts_rth_cfg);
19021256Syl150051 
19031256Syl150051 	xge_debug_device(XGE_TRACE, "RTH configured, bucket_size %d",
19041256Syl150051 			  hldev->config.rth_bucket_size);
19051256Syl150051 
19061256Syl150051 	return XGE_HAL_OK;
19071256Syl150051 }
19081256Syl150051 
19091256Syl150051 
19101256Syl150051 /*
19111256Syl150051  * __hal_spdm_entry_add - Add a new entry to the SPDM table.
19121256Syl150051  *
19131256Syl150051  * Add a new entry to the SPDM table
19141256Syl150051  *
19151256Syl150051  * This function add a new entry to the SPDM table.
19161256Syl150051  *
19171256Syl150051  * Note:
19181256Syl150051  *   This function should be called with spdm_lock.
19191256Syl150051  *
19201256Syl150051  * See also: xge_hal_spdm_entry_add , xge_hal_spdm_entry_remove.
19211256Syl150051  */
19221256Syl150051 static xge_hal_status_e
__hal_spdm_entry_add(xge_hal_device_t * hldev,xge_hal_ipaddr_t * src_ip,xge_hal_ipaddr_t * dst_ip,u16 l4_sp,u16 l4_dp,u8 is_tcp,u8 is_ipv4,u8 tgt_queue,u32 jhash_value,u16 spdm_entry)19231256Syl150051 __hal_spdm_entry_add(xge_hal_device_t *hldev, xge_hal_ipaddr_t *src_ip,
19241256Syl150051 		xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp, u8 is_tcp,
19251256Syl150051 		u8 is_ipv4, u8 tgt_queue, u32 jhash_value, u16 spdm_entry)
19261256Syl150051 {
19271256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
19281256Syl150051 	u64 val64;
19291256Syl150051 	u64 spdm_line_arr[8];
19301256Syl150051 	u8 line_no;
19311256Syl150051 
19321256Syl150051 	/*
19331256Syl150051 	 * Clear the SPDM READY bit
19341256Syl150051 	 */
19353115Syl150051 	val64 = XGE_HAL_RX_PIC_INT_REG_SPDM_READY;
19361256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
19371256Syl150051 			       &bar0->rxpic_int_reg);
19381256Syl150051 
19391256Syl150051 	xge_debug_device(XGE_TRACE,
19406937Sxw161283 			"L4 SP %x:DP %x: hash %x tgt_queue %d ",
19411256Syl150051 			l4_sp, l4_dp, jhash_value, tgt_queue);
19421256Syl150051 
19431256Syl150051 	xge_os_memzero(&spdm_line_arr, sizeof(spdm_line_arr));
19441256Syl150051 
19451256Syl150051 	/*
19461256Syl150051 	 * Construct the SPDM entry.
19471256Syl150051 	 */
19481256Syl150051 	spdm_line_arr[0] = vBIT(l4_sp,0,16) |
19491256Syl150051 			   vBIT(l4_dp,16,32) |
19501256Syl150051 			   vBIT(tgt_queue,53,3)	|
19511256Syl150051 			   vBIT(is_tcp,59,1) |
19521256Syl150051 			   vBIT(is_ipv4,63,1);
19531256Syl150051 
19541256Syl150051 
19551256Syl150051 	if (is_ipv4) {
19561256Syl150051 		spdm_line_arr[1] = vBIT(src_ip->ipv4.addr,0,32) |
19571256Syl150051 				   vBIT(dst_ip->ipv4.addr,32,32);
19581256Syl150051 
19591256Syl150051 	} else {
19601256Syl150051 		xge_os_memcpy(&spdm_line_arr[1], &src_ip->ipv6.addr[0], 8);
19611256Syl150051 		xge_os_memcpy(&spdm_line_arr[2], &src_ip->ipv6.addr[1], 8);
19621256Syl150051 		xge_os_memcpy(&spdm_line_arr[3], &dst_ip->ipv6.addr[0], 8);
19631256Syl150051 		xge_os_memcpy(&spdm_line_arr[4], &dst_ip->ipv6.addr[1], 8);
19641256Syl150051 	}
19651256Syl150051 
19661256Syl150051 	spdm_line_arr[7] = vBIT(jhash_value,0,32) |
19671256Syl150051 				BIT(63);  /* entry enable bit */
19681256Syl150051 
19691256Syl150051 	/*
19701256Syl150051 	 * Add the entry to the SPDM table
19711256Syl150051 	 */
19721256Syl150051 	for(line_no = 0; line_no < 8; line_no++) {
19731256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
19741256Syl150051 				spdm_line_arr[line_no],
19751256Syl150051 				(void *)((char *)hldev->spdm_mem_base +
19761256Syl150051 						(spdm_entry * 64) +
19771256Syl150051 						(line_no * 8)));
19781256Syl150051 	}
19791256Syl150051 
19801256Syl150051 	/*
19811256Syl150051 	 * Wait for the operation to be completed.
19821256Syl150051 	 */
19831256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1,
19841256Syl150051 			XGE_HAL_RX_PIC_INT_REG_SPDM_READY,
19851256Syl150051 			XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
19861256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
19871256Syl150051 	}
19881256Syl150051 
19891256Syl150051 	/*
19901256Syl150051 	 * Add this information to a local SPDM table. The purpose of
19911256Syl150051 	 * maintaining a local SPDM table is to avoid a search in the
19921256Syl150051 	 * adapter SPDM table for spdm entry lookup which is very costly
19931256Syl150051 	 * in terms of time.
19941256Syl150051 	 */
19951256Syl150051 	hldev->spdm_table[spdm_entry]->in_use = 1;
19961256Syl150051 	xge_os_memcpy(&hldev->spdm_table[spdm_entry]->src_ip, src_ip,
19971256Syl150051 		    sizeof(xge_hal_ipaddr_t));
19981256Syl150051 	xge_os_memcpy(&hldev->spdm_table[spdm_entry]->dst_ip, dst_ip,
19991256Syl150051 		    sizeof(xge_hal_ipaddr_t));
20001256Syl150051 	hldev->spdm_table[spdm_entry]->l4_sp = l4_sp;
20011256Syl150051 	hldev->spdm_table[spdm_entry]->l4_dp = l4_dp;
20021256Syl150051 	hldev->spdm_table[spdm_entry]->is_tcp = is_tcp;
20031256Syl150051 	hldev->spdm_table[spdm_entry]->is_ipv4 = is_ipv4;
20041256Syl150051 	hldev->spdm_table[spdm_entry]->tgt_queue = tgt_queue;
20051256Syl150051 	hldev->spdm_table[spdm_entry]->jhash_value = jhash_value;
20061256Syl150051 	hldev->spdm_table[spdm_entry]->spdm_entry = spdm_entry;
20071256Syl150051 
20081256Syl150051 	return XGE_HAL_OK;
20091256Syl150051 }
20101256Syl150051 
20111256Syl150051 /*
20121256Syl150051  * __hal_device_rth_spdm_configure - Configure RTH for the device
20131256Syl150051  * @hldev: HAL device handle.
20141256Syl150051  *
20151256Syl150051  * Using SPDM (Socket-Pair Direct Match).
20161256Syl150051  */
20171256Syl150051 xge_hal_status_e
__hal_device_rth_spdm_configure(xge_hal_device_t * hldev)20181256Syl150051 __hal_device_rth_spdm_configure(xge_hal_device_t *hldev)
20191256Syl150051 {
20201256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
20211256Syl150051 	u64 val64;
20221256Syl150051 	u8 spdm_bar_num;
20231256Syl150051 	u32 spdm_bar_offset;
20241256Syl150051 	int spdm_table_size;
20251256Syl150051 	int i;
20261256Syl150051 
20271256Syl150051 	if (!hldev->config.rth_spdm_en) {
20281256Syl150051 		return XGE_HAL_OK;
20291256Syl150051 	}
20301256Syl150051 
20311256Syl150051 	/*
20321256Syl150051 	 * Retrieve the base address of SPDM Table.
20331256Syl150051 	 */
20341256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev,
20351256Syl150051 			hldev->regh0, &bar0->spdm_bir_offset);
20361256Syl150051 
20371256Syl150051 	spdm_bar_num	= XGE_HAL_SPDM_PCI_BAR_NUM(val64);
20381256Syl150051 	spdm_bar_offset	= XGE_HAL_SPDM_PCI_BAR_OFFSET(val64);
20391256Syl150051 
20401256Syl150051 
20411256Syl150051 	/*
20421256Syl150051 	 * spdm_bar_num specifies the PCI bar num register used to
20431256Syl150051 	 * address the memory space. spdm_bar_offset specifies the offset
20441256Syl150051 	 * of the SPDM memory with in the bar num memory space.
20451256Syl150051 	 */
20461256Syl150051 	switch (spdm_bar_num) {
20471256Syl150051 		case 0:
20481256Syl150051 		{
20491256Syl150051 			hldev->spdm_mem_base = (char *)bar0 +
20501256Syl150051 						(spdm_bar_offset * 8);
20511256Syl150051 			break;
20521256Syl150051 		}
20531256Syl150051 		case 1:
20541256Syl150051 		{
20551256Syl150051 			char *bar1 = (char *)hldev->bar1;
20561256Syl150051 			hldev->spdm_mem_base = bar1 + (spdm_bar_offset * 8);
20571256Syl150051 			break;
20581256Syl150051 		}
20591256Syl150051 		default:
20601256Syl150051 			xge_assert(((spdm_bar_num != 0) && (spdm_bar_num != 1)));
20611256Syl150051 	}
20621256Syl150051 
20631256Syl150051 	/*
20641256Syl150051 	 * Retrieve the size of SPDM table(number of entries).
20651256Syl150051 	 */
20661256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev,
20671256Syl150051 			hldev->regh0, &bar0->spdm_structure);
20681256Syl150051 	hldev->spdm_max_entries = XGE_HAL_SPDM_MAX_ENTRIES(val64);
20691256Syl150051 
20701256Syl150051 
20711256Syl150051 	spdm_table_size = hldev->spdm_max_entries *
20721256Syl150051 					sizeof(xge_hal_spdm_entry_t);
20731256Syl150051 	if (hldev->spdm_table == NULL) {
20741256Syl150051 		void *mem;
20751256Syl150051 
20761256Syl150051 		/*
20771256Syl150051 		 * Allocate memory to hold the copy of SPDM table.
20781256Syl150051 		 */
20791256Syl150051 		if ((hldev->spdm_table = (xge_hal_spdm_entry_t **)
20801256Syl150051 					xge_os_malloc(
20811256Syl150051 					 hldev->pdev,
20821256Syl150051 					 (sizeof(xge_hal_spdm_entry_t *) *
20831256Syl150051 					 hldev->spdm_max_entries))) == NULL) {
20841256Syl150051 			return XGE_HAL_ERR_OUT_OF_MEMORY;
20851256Syl150051 		}
20861256Syl150051 
20871256Syl150051 		if ((mem = xge_os_malloc(hldev->pdev, spdm_table_size)) == NULL)
20881256Syl150051 		{
20891256Syl150051 			xge_os_free(hldev->pdev, hldev->spdm_table,
20901256Syl150051 				  (sizeof(xge_hal_spdm_entry_t *) *
20911256Syl150051 					 hldev->spdm_max_entries));
20921256Syl150051 			return XGE_HAL_ERR_OUT_OF_MEMORY;
20931256Syl150051 		}
20941256Syl150051 
20951256Syl150051 		xge_os_memzero(mem, spdm_table_size);
20961256Syl150051 		for (i = 0; i < hldev->spdm_max_entries; i++) {
20971256Syl150051 			hldev->spdm_table[i] = (xge_hal_spdm_entry_t *)
20981256Syl150051 					((char *)mem +
20991256Syl150051 					 i * sizeof(xge_hal_spdm_entry_t));
21001256Syl150051 		}
21011256Syl150051 		xge_os_spin_lock_init(&hldev->spdm_lock, hldev->pdev);
21021256Syl150051 	} else {
21031256Syl150051 		/*
21041256Syl150051 		 * We are here because the host driver tries to
21051256Syl150051 		 * do a soft reset on the device.
21061256Syl150051 		 * Since the device soft reset clears the SPDM table, copy
21071256Syl150051 		 * the entries from the local SPDM table to the actual one.
21081256Syl150051 		 */
21091256Syl150051 		xge_os_spin_lock(&hldev->spdm_lock);
21101256Syl150051 		for (i = 0; i < hldev->spdm_max_entries; i++) {
21111256Syl150051 			xge_hal_spdm_entry_t *spdm_entry = hldev->spdm_table[i];
21121256Syl150051 
21131256Syl150051 			if (spdm_entry->in_use) {
21141256Syl150051 				if (__hal_spdm_entry_add(hldev,
21151256Syl150051 							 &spdm_entry->src_ip,
21161256Syl150051 							 &spdm_entry->dst_ip,
21171256Syl150051 							 spdm_entry->l4_sp,
21181256Syl150051 							 spdm_entry->l4_dp,
21191256Syl150051 							 spdm_entry->is_tcp,
21201256Syl150051 							 spdm_entry->is_ipv4,
21211256Syl150051 							 spdm_entry->tgt_queue,
21221256Syl150051 							 spdm_entry->jhash_value,
21231256Syl150051 							 spdm_entry->spdm_entry)
21241256Syl150051 						!= XGE_HAL_OK) {
21251256Syl150051 					/* Log an warning */
21266937Sxw161283 					xge_debug_device(XGE_ERR,
21271256Syl150051 						"SPDM table update from local"
21281256Syl150051 						" memory failed");
21291256Syl150051 				}
21301256Syl150051 			}
21311256Syl150051 		}
21321256Syl150051 		xge_os_spin_unlock(&hldev->spdm_lock);
21331256Syl150051 	}
21341256Syl150051 
21351256Syl150051 	/*
21361256Syl150051 	 * Set the receive traffic steering mode from default(classic)
21371256Syl150051 	 * to enhanced.
21381256Syl150051 	 */
21391256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev,
21401256Syl150051 				    hldev->regh0, &bar0->rts_ctrl);
21411256Syl150051 	val64 |=  XGE_HAL_RTS_CTRL_ENHANCED_MODE;
21421256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
21431256Syl150051 			     val64, &bar0->rts_ctrl);
21441256Syl150051 
21451256Syl150051 	/*
21461256Syl150051 	 * We may not need to configure rts_rth_jhash_cfg register as the
21471256Syl150051 	 * default values are good enough to calculate the hash.
21481256Syl150051 	 */
21491256Syl150051 
21501256Syl150051 	/*
21511256Syl150051 	 * As of now, set all the rth mask registers to zero. TODO.
21521256Syl150051 	 */
21531256Syl150051 	for(i = 0; i < 5; i++) {
21541256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
21551256Syl150051 				     0, &bar0->rts_rth_hash_mask[i]);
21561256Syl150051 	}
21571256Syl150051 
21581256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
21591256Syl150051 			     0, &bar0->rts_rth_hash_mask_5);
21601256Syl150051 
21611256Syl150051 	if (hldev->config.rth_spdm_use_l4) {
21621256Syl150051 		val64 = XGE_HAL_RTH_STATUS_SPDM_USE_L4;
21631256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
21641256Syl150051 				     val64, &bar0->rts_rth_status);
21651256Syl150051 	}
21661256Syl150051 
21671256Syl150051 	val64 = XGE_HAL_RTS_RTH_EN;
21681256Syl150051 	val64 |= XGE_HAL_RTS_RTH_IPV4_EN | XGE_HAL_RTS_RTH_TCP_IPV4_EN;
21691256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
21701256Syl150051 			     &bar0->rts_rth_cfg);
21711256Syl150051 
21721256Syl150051 
21731256Syl150051 	return XGE_HAL_OK;
21741256Syl150051 }
21751256Syl150051 
21761256Syl150051 /*
21771256Syl150051  * __hal_device_pci_init
21781256Syl150051  * @hldev: HAL device handle.
21791256Syl150051  *
21801256Syl150051  * Initialize certain PCI/PCI-X configuration registers
21811256Syl150051  * with recommended values. Save config space for future hw resets.
21821256Syl150051  */
21831256Syl150051 static void
__hal_device_pci_init(xge_hal_device_t * hldev)21841256Syl150051 __hal_device_pci_init(xge_hal_device_t *hldev)
21851256Syl150051 {
21861256Syl150051 	int i, pcisize = 0;
21871256Syl150051 	u16 cmd = 0;
21881256Syl150051 	u8  val;
21891256Syl150051 
21906937Sxw161283 	/* Store PCI device ID and revision for future references where in we
21916937Sxw161283 	 * decide Xena revision using PCI sub system ID */
21926937Sxw161283 	xge_os_pci_read16(hldev->pdev,hldev->cfgh,
21936937Sxw161283 			xge_offsetof(xge_hal_pci_config_le_t, device_id),
21946937Sxw161283 			&hldev->device_id);
21956937Sxw161283 	xge_os_pci_read8(hldev->pdev,hldev->cfgh,
21966937Sxw161283 			xge_offsetof(xge_hal_pci_config_le_t, revision),
21976937Sxw161283 			&hldev->revision);
21986937Sxw161283 
21996937Sxw161283 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
22006937Sxw161283 		pcisize = XGE_HAL_PCISIZE_HERC;
22016937Sxw161283 	else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)
22026937Sxw161283 		pcisize = XGE_HAL_PCISIZE_XENA;
22036937Sxw161283 
22046937Sxw161283 	/* save original PCI config space to restore it on device_terminate() */
22056937Sxw161283 	for (i = 0; i < pcisize; i++) {
22066937Sxw161283 		xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4,
22076937Sxw161283 		                (u32*)&hldev->pci_config_space_bios + i);
22086937Sxw161283 	}
22096937Sxw161283 
22101256Syl150051 	/* Set the PErr Repconse bit and SERR in PCI command register. */
22111256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
22121256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, command), &cmd);
22131256Syl150051 	cmd |= 0x140;
22141256Syl150051 	xge_os_pci_write16(hldev->pdev, hldev->cfgh,
22151256Syl150051 			 xge_offsetof(xge_hal_pci_config_le_t, command), cmd);
22161256Syl150051 
22171256Syl150051 	/* Set user spcecified value for the PCI Latency Timer */
22181256Syl150051 	if (hldev->config.latency_timer &&
22191256Syl150051 	    hldev->config.latency_timer != XGE_HAL_USE_BIOS_DEFAULT_LATENCY) {
22201256Syl150051 		xge_os_pci_write8(hldev->pdev, hldev->cfgh,
22211256Syl150051 	                 xge_offsetof(xge_hal_pci_config_le_t,
22221256Syl150051 	                 latency_timer),
22231256Syl150051 			 (u8)hldev->config.latency_timer);
22241256Syl150051 	}
22251256Syl150051 	/* Read back latency timer to reflect it into user level */
22261256Syl150051 	xge_os_pci_read8(hldev->pdev, hldev->cfgh,
22271256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, latency_timer), &val);
22281256Syl150051 	hldev->config.latency_timer = val;
22291256Syl150051 
22301256Syl150051 	/* Enable Data Parity Error Recovery in PCI-X command register. */
22311256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
22321256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd);
22331256Syl150051 	cmd |= 1;
22341256Syl150051 	xge_os_pci_write16(hldev->pdev, hldev->cfgh,
22351256Syl150051 		 xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd);
22361256Syl150051 
22371256Syl150051 	/* Set MMRB count in PCI-X command register. */
22381256Syl150051 	if (hldev->config.mmrb_count != XGE_HAL_DEFAULT_BIOS_MMRB_COUNT) {
22391256Syl150051 		cmd &= 0xFFF3;
22401256Syl150051 		cmd |= hldev->config.mmrb_count << 2;
22411256Syl150051 		xge_os_pci_write16(hldev->pdev, hldev->cfgh,
22421256Syl150051 		       xge_offsetof(xge_hal_pci_config_le_t, pcix_command),
22431256Syl150051 		       cmd);
22441256Syl150051 	}
22451256Syl150051 	/* Read back MMRB count to reflect it into user level */
22461256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
22471256Syl150051 		        xge_offsetof(xge_hal_pci_config_le_t, pcix_command),
22481256Syl150051 		        &cmd);
22491256Syl150051 	cmd &= 0x000C;
22501256Syl150051 	hldev->config.mmrb_count = cmd>>2;
22511256Syl150051 
22521256Syl150051 	/*  Setting Maximum outstanding splits based on system type. */
22531256Syl150051 	if (hldev->config.max_splits_trans != XGE_HAL_USE_BIOS_DEFAULT_SPLITS)  {
22541256Syl150051 		xge_os_pci_read16(hldev->pdev, hldev->cfgh,
22551256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, pcix_command),
22561256Syl150051 			&cmd);
22571256Syl150051 		cmd &= 0xFF8F;
22581256Syl150051 		cmd |= hldev->config.max_splits_trans << 4;
22591256Syl150051 		xge_os_pci_write16(hldev->pdev, hldev->cfgh,
22601256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, pcix_command),
22611256Syl150051 			cmd);
22621256Syl150051 	}
22631256Syl150051 
22641256Syl150051 	/* Read back max split trans to reflect it into user level */
22651256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
22661256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd);
22671256Syl150051 	cmd &= 0x0070;
22681256Syl150051 	hldev->config.max_splits_trans = cmd>>4;
22691256Syl150051 
22701256Syl150051 	/* Forcibly disabling relaxed ordering capability of the card. */
22711256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
22721256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, pcix_command), &cmd);
22731256Syl150051 	cmd &= 0xFFFD;
22741256Syl150051 	xge_os_pci_write16(hldev->pdev, hldev->cfgh,
22751256Syl150051 		 xge_offsetof(xge_hal_pci_config_le_t, pcix_command), cmd);
22761256Syl150051 
22771256Syl150051 	/* save PCI config space for future resets */
22781256Syl150051 	for (i = 0; i < pcisize; i++) {
22791256Syl150051 		xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4,
22801256Syl150051 		                (u32*)&hldev->pci_config_space + i);
22811256Syl150051 	}
22821256Syl150051 }
22831256Syl150051 
22841256Syl150051 /*
22851256Syl150051  * __hal_device_pci_info_get - Get PCI bus informations such as width, frequency
22861256Syl150051  *                               and mode.
22871256Syl150051  * @devh: HAL device handle.
22881256Syl150051  * @pci_mode:		pointer to a variable of enumerated type
22891256Syl150051  *			xge_hal_pci_mode_e{}.
22901256Syl150051  * @bus_frequency:	pointer to a variable of enumerated type
22911256Syl150051  *			xge_hal_pci_bus_frequency_e{}.
22921256Syl150051  * @bus_width:		pointer to a variable of enumerated type
22931256Syl150051  *			xge_hal_pci_bus_width_e{}.
22941256Syl150051  *
22951256Syl150051  * Get pci mode, frequency, and PCI bus width.
22961256Syl150051  *
22971256Syl150051  * Returns: one of the xge_hal_status_e{} enumerated types.
22981256Syl150051  * XGE_HAL_OK			- for success.
22991256Syl150051  * XGE_HAL_ERR_INVALID_PCI_INFO - for invalid PCI information from the card.
23001256Syl150051  * XGE_HAL_ERR_BAD_DEVICE_ID	- for invalid card.
23011256Syl150051  *
23021256Syl150051  * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e.
23031256Syl150051  */
23041256Syl150051 static xge_hal_status_e
__hal_device_pci_info_get(xge_hal_device_h devh,xge_hal_pci_mode_e * pci_mode,xge_hal_pci_bus_frequency_e * bus_frequency,xge_hal_pci_bus_width_e * bus_width)23051256Syl150051 __hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode,
23061256Syl150051 		xge_hal_pci_bus_frequency_e *bus_frequency,
23071256Syl150051 		xge_hal_pci_bus_width_e *bus_width)
23081256Syl150051 {
23091256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
23101256Syl150051 	xge_hal_status_e rc_status = XGE_HAL_OK;
23111256Syl150051 	xge_hal_card_e card_id	   = xge_hal_device_check_id (devh);
23121256Syl150051 
23131256Syl150051 #ifdef XGE_HAL_HERC_EMULATION
23141256Syl150051 	hldev->config.pci_freq_mherz =
23151256Syl150051 		XGE_HAL_PCI_BUS_FREQUENCY_66MHZ;
23161256Syl150051 	*bus_frequency	=
23171256Syl150051 		XGE_HAL_PCI_BUS_FREQUENCY_66MHZ;
23181256Syl150051 	*pci_mode = XGE_HAL_PCI_66MHZ_MODE;
23191256Syl150051 #else
23201256Syl150051 	if (card_id == XGE_HAL_CARD_HERC) {
23211256Syl150051 		xge_hal_pci_bar0_t *bar0 =
23221256Syl150051 		(xge_hal_pci_bar0_t *)(void *)hldev->bar0;
23231256Syl150051 		u64 pci_info = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
23241256Syl150051 				    &bar0->pci_info);
23251256Syl150051 		if (XGE_HAL_PCI_32_BIT & pci_info)
23261256Syl150051 			*bus_width = XGE_HAL_PCI_BUS_WIDTH_32BIT;
23271256Syl150051 		else
23281256Syl150051 			*bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT;
23291256Syl150051 		switch((pci_info & XGE_HAL_PCI_INFO)>>60)
23301256Syl150051 		{
23311256Syl150051 			case XGE_HAL_PCI_33MHZ_MODE:
23321256Syl150051 				 *bus_frequency	=
23331256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_33MHZ;
23341256Syl150051 				 *pci_mode = XGE_HAL_PCI_33MHZ_MODE;
23351256Syl150051 				 break;
23361256Syl150051 			case XGE_HAL_PCI_66MHZ_MODE:
23371256Syl150051 				 *bus_frequency	=
23381256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_66MHZ;
23391256Syl150051 				 *pci_mode = XGE_HAL_PCI_66MHZ_MODE;
23401256Syl150051 				 break;
23411256Syl150051 			case XGE_HAL_PCIX_M1_66MHZ_MODE:
23421256Syl150051 				 *bus_frequency	=
23431256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_66MHZ;
23441256Syl150051 				 *pci_mode = XGE_HAL_PCIX_M1_66MHZ_MODE;
23451256Syl150051 				 break;
23461256Syl150051 			case XGE_HAL_PCIX_M1_100MHZ_MODE:
23471256Syl150051 				 *bus_frequency	=
23481256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_100MHZ;
23491256Syl150051 				 *pci_mode = XGE_HAL_PCIX_M1_100MHZ_MODE;
23501256Syl150051 				 break;
23511256Syl150051 			case XGE_HAL_PCIX_M1_133MHZ_MODE:
23521256Syl150051 				 *bus_frequency	=
23531256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_133MHZ;
23541256Syl150051 				 *pci_mode = XGE_HAL_PCIX_M1_133MHZ_MODE;
23551256Syl150051 				 break;
23561256Syl150051 			case XGE_HAL_PCIX_M2_66MHZ_MODE:
23571256Syl150051 				 *bus_frequency	=
23581256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_133MHZ;
23591256Syl150051 				 *pci_mode = XGE_HAL_PCIX_M2_66MHZ_MODE;
23601256Syl150051 				 break;
23611256Syl150051 			case XGE_HAL_PCIX_M2_100MHZ_MODE:
23621256Syl150051 				 *bus_frequency	=
23631256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_200MHZ;
23641256Syl150051 				 *pci_mode = XGE_HAL_PCIX_M2_100MHZ_MODE;
23651256Syl150051 				 break;
23661256Syl150051 			case XGE_HAL_PCIX_M2_133MHZ_MODE:
23671256Syl150051 				 *bus_frequency	=
23681256Syl150051 					 XGE_HAL_PCI_BUS_FREQUENCY_266MHZ;
23691256Syl150051 				 *pci_mode = XGE_HAL_PCIX_M2_133MHZ_MODE;
23701256Syl150051 				  break;
23711256Syl150051 			case XGE_HAL_PCIX_M1_RESERVED:
23721256Syl150051 			case XGE_HAL_PCIX_M1_66MHZ_NS:
23731256Syl150051 			case XGE_HAL_PCIX_M1_100MHZ_NS:
23741256Syl150051 			case XGE_HAL_PCIX_M1_133MHZ_NS:
23751256Syl150051 			case XGE_HAL_PCIX_M2_RESERVED:
23761256Syl150051 			case XGE_HAL_PCIX_533_RESERVED:
23771256Syl150051 			default:
23781256Syl150051 				 rc_status = XGE_HAL_ERR_INVALID_PCI_INFO;
23791256Syl150051 				 xge_debug_device(XGE_ERR,
23803115Syl150051 					  "invalid pci info "XGE_OS_LLXFMT,
23811256Syl150051 					 (unsigned long long)pci_info);
23821256Syl150051 				 break;
23831256Syl150051 		}
23841256Syl150051 		if (rc_status != XGE_HAL_ERR_INVALID_PCI_INFO)
23851256Syl150051 			xge_debug_device(XGE_TRACE, "PCI info: mode %d width "
23861256Syl150051 				"%d frequency %d", *pci_mode, *bus_width,
23871256Syl150051 				*bus_frequency);
23883115Syl150051 		if (hldev->config.pci_freq_mherz ==
23893115Syl150051 				XGE_HAL_DEFAULT_USE_HARDCODE) {
23903115Syl150051 			hldev->config.pci_freq_mherz = *bus_frequency;
23913115Syl150051 		}
23921256Syl150051 	}
23931256Syl150051 	/* for XENA, we report PCI mode, only. PCI bus frequency, and bus width
23941256Syl150051 	 * are set to unknown */
23951256Syl150051 	else if (card_id == XGE_HAL_CARD_XENA) {
23961256Syl150051 		u32 pcix_status;
23971256Syl150051 		u8 dev_num, bus_num;
23981256Syl150051 		/* initialize defaults for XENA */
23991256Syl150051 		*bus_frequency	= XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN;
24001256Syl150051 		*bus_width	= XGE_HAL_PCI_BUS_WIDTH_UNKNOWN;
24011256Syl150051 		xge_os_pci_read32(hldev->pdev, hldev->cfgh,
24021256Syl150051 			xge_offsetof(xge_hal_pci_config_le_t, pcix_status),
24031256Syl150051 			&pcix_status);
24041256Syl150051 		dev_num = (u8)((pcix_status & 0xF8) >> 3);
24051256Syl150051 		bus_num = (u8)((pcix_status & 0xFF00) >> 8);
24061256Syl150051 		if (dev_num == 0 && bus_num == 0)
24071256Syl150051 			*pci_mode = XGE_HAL_PCI_BASIC_MODE;
24081256Syl150051 		else
24091256Syl150051 			*pci_mode = XGE_HAL_PCIX_BASIC_MODE;
24101256Syl150051 		xge_debug_device(XGE_TRACE, "PCI info: mode %d", *pci_mode);
24111256Syl150051 		if (hldev->config.pci_freq_mherz ==
24121256Syl150051 				XGE_HAL_DEFAULT_USE_HARDCODE) {
24131256Syl150051 			/*
24141256Syl150051 			 * There is no way to detect BUS frequency on Xena,
24151256Syl150051 			 * so, in case of automatic configuration we hopelessly
24161256Syl150051 			 * assume 133MHZ.
24171256Syl150051 			 */
24181256Syl150051 			hldev->config.pci_freq_mherz =
24191256Syl150051 				XGE_HAL_PCI_BUS_FREQUENCY_133MHZ;
24201256Syl150051 		}
24216937Sxw161283 	} else if (card_id == XGE_HAL_CARD_TITAN) {
24226937Sxw161283 		*bus_width = XGE_HAL_PCI_BUS_WIDTH_64BIT;
24236937Sxw161283 		*bus_frequency	= XGE_HAL_PCI_BUS_FREQUENCY_250MHZ;
24246937Sxw161283 		if (hldev->config.pci_freq_mherz ==
24256937Sxw161283 				XGE_HAL_DEFAULT_USE_HARDCODE) {
24266937Sxw161283 			hldev->config.pci_freq_mherz = *bus_frequency;
24276937Sxw161283 		}
24281256Syl150051 	} else{
24291256Syl150051 		rc_status =  XGE_HAL_ERR_BAD_DEVICE_ID;
24301256Syl150051 		xge_debug_device(XGE_ERR, "invalid device id %d", card_id);
24311256Syl150051 	}
24321256Syl150051 #endif
24331256Syl150051 
24341256Syl150051 	return rc_status;
24351256Syl150051 }
24361256Syl150051 
24371256Syl150051 /*
24381256Syl150051  * __hal_device_handle_link_up_ind
24391256Syl150051  * @hldev: HAL device handle.
24401256Syl150051  *
24411256Syl150051  * Link up indication handler. The function is invoked by HAL when
24421256Syl150051  * Xframe indicates that the link is up for programmable amount of time.
24431256Syl150051  */
24441256Syl150051 static int
__hal_device_handle_link_up_ind(xge_hal_device_t * hldev)24451256Syl150051 __hal_device_handle_link_up_ind(xge_hal_device_t *hldev)
24461256Syl150051 {
24471256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
24481256Syl150051 	u64 val64;
24491256Syl150051 
24501256Syl150051 	/*
24511256Syl150051 	 * If the previous link state is not down, return.
24521256Syl150051 	 */
24531256Syl150051 	if (hldev->link_state == XGE_HAL_LINK_UP) {
24541256Syl150051 #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR
24551256Syl150051 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){
24561256Syl150051 			val64 = xge_os_pio_mem_read64(
24571256Syl150051 				hldev->pdev, hldev->regh0,
24581256Syl150051 				&bar0->misc_int_mask);
24591256Syl150051 			val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT;
24601256Syl150051 			val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT;
24611256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
24621256Syl150051 				val64, &bar0->misc_int_mask);
24631256Syl150051 		}
24641256Syl150051 #endif
24651256Syl150051 		xge_debug_device(XGE_TRACE,
24661256Syl150051 			"link up indication while link is up, ignoring..");
24671256Syl150051 		return 0;
24681256Syl150051 	}
24691256Syl150051 
24701256Syl150051 	/* Now re-enable it as due to noise, hardware turned it off */
24711256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
24721256Syl150051 				     &bar0->adapter_control);
24731256Syl150051 	val64 |= XGE_HAL_ADAPTER_CNTL_EN;
24741256Syl150051 	val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */
24751256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
24761256Syl150051 			     &bar0->adapter_control);
24771256Syl150051 
24781256Syl150051 	/* Turn on the Laser */
24791256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
24801256Syl150051 				    &bar0->adapter_control);
24811256Syl150051 	val64 = val64|(XGE_HAL_ADAPTER_EOI_TX_ON |
24821256Syl150051 			XGE_HAL_ADAPTER_LED_ON);
24831256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
24841256Syl150051 			     &bar0->adapter_control);
24851256Syl150051 
24861256Syl150051 #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR
24871256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
24881256Syl150051 	        val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
24891256Syl150051 				              &bar0->adapter_status);
24901256Syl150051 	        if (val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
24911256Syl150051 		             XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) {
24921256Syl150051 		        xge_debug_device(XGE_TRACE, "%s",
24931256Syl150051 				          "fail to transition link to up...");
24941256Syl150051 			return 0;
24951256Syl150051 	        }
24961256Syl150051 	        else {
24971256Syl150051 		        /*
24981256Syl150051 		         * Mask the Link Up interrupt and unmask the Link Down
24991256Syl150051 		         * interrupt.
25001256Syl150051 		         */
25011256Syl150051 		        val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
25021256Syl150051 					              &bar0->misc_int_mask);
25031256Syl150051 		        val64 |= XGE_HAL_MISC_INT_REG_LINK_UP_INT;
25041256Syl150051 		        val64 &= ~XGE_HAL_MISC_INT_REG_LINK_DOWN_INT;
25051256Syl150051 		        xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
25061256Syl150051 				               &bar0->misc_int_mask);
25071256Syl150051 		        xge_debug_device(XGE_TRACE, "calling link up..");
25081256Syl150051 		        hldev->link_state = XGE_HAL_LINK_UP;
25091256Syl150051 
25101256Syl150051 		        /* notify ULD */
25111256Syl150051 		        if (g_xge_hal_driver->uld_callbacks.link_up) {
25121256Syl150051 			        g_xge_hal_driver->uld_callbacks.link_up(
25131256Syl150051 					        hldev->upper_layer_info);
25141256Syl150051 		        }
25151256Syl150051 			return 1;
25161256Syl150051 	        }
25171256Syl150051         }
25181256Syl150051 #endif
25191256Syl150051 	xge_os_mdelay(1);
25201256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0,
25211256Syl150051 			(XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
25221256Syl150051 			XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT),
25231256Syl150051 			XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) {
25241256Syl150051 
25251256Syl150051 		/* notify ULD */
25261256Syl150051 		(void) xge_queue_produce_context(hldev->queueh,
25276937Sxw161283 						 XGE_HAL_EVENT_LINK_IS_UP, hldev);
25281256Syl150051 		/* link is up after been enabled */
25291256Syl150051 		return 1;
25301256Syl150051 	} else {
25311256Syl150051 		xge_debug_device(XGE_TRACE, "%s",
25321256Syl150051 				  "fail to transition link to up...");
25331256Syl150051 		return 0;
25341256Syl150051 	}
25351256Syl150051 }
25361256Syl150051 
25371256Syl150051 /*
25381256Syl150051  * __hal_device_handle_link_down_ind
25391256Syl150051  * @hldev: HAL device handle.
25401256Syl150051  *
25411256Syl150051  * Link down indication handler. The function is invoked by HAL when
25421256Syl150051  * Xframe indicates that the link is down.
25431256Syl150051  */
25441256Syl150051 static int
__hal_device_handle_link_down_ind(xge_hal_device_t * hldev)25451256Syl150051 __hal_device_handle_link_down_ind(xge_hal_device_t *hldev)
25461256Syl150051 {
25471256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
25481256Syl150051 	u64 val64;
25491256Syl150051 
25501256Syl150051 	/*
25511256Syl150051 	 * If the previous link state is not up, return.
25521256Syl150051 	 */
25531256Syl150051 	if (hldev->link_state == XGE_HAL_LINK_DOWN) {
25541256Syl150051 #ifdef	XGE_HAL_PROCESS_LINK_INT_IN_ISR
25551256Syl150051 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC){
25561256Syl150051 			val64 = xge_os_pio_mem_read64(
25571256Syl150051 				hldev->pdev, hldev->regh0,
25581256Syl150051 				&bar0->misc_int_mask);
25591256Syl150051 			val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT;
25601256Syl150051 			val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT;
25611256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
25621256Syl150051 				val64, &bar0->misc_int_mask);
25631256Syl150051 		}
25641256Syl150051 #endif
25651256Syl150051 		xge_debug_device(XGE_TRACE,
25661256Syl150051 			"link down indication while link is down, ignoring..");
25671256Syl150051 		return 0;
25681256Syl150051 	}
25691256Syl150051 	xge_os_mdelay(1);
25701256Syl150051 
25711256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
25721256Syl150051 				      &bar0->adapter_control);
25731256Syl150051 
25741256Syl150051 	/* try to debounce the link only if the adapter is enabled. */
25751256Syl150051 	if (val64 & XGE_HAL_ADAPTER_CNTL_EN) {
25761256Syl150051 		if (__hal_device_register_poll(hldev, &bar0->adapter_status, 0,
25771256Syl150051 			(XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
25781256Syl150051 			XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT),
25791256Syl150051 			XGE_HAL_DEVICE_FAULT_WAIT_MAX_MILLIS) == XGE_HAL_OK) {
25801256Syl150051 			xge_debug_device(XGE_TRACE,
25811256Syl150051 				"link is actually up (possible noisy link?), ignoring.");
25821256Syl150051 			return(0);
25831256Syl150051 		}
25841256Syl150051 	}
25851256Syl150051 
25861256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
25871256Syl150051 				    &bar0->adapter_control);
25881256Syl150051 	/* turn off LED */
25891256Syl150051 	val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON);
25901256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
25911256Syl150051 			       &bar0->adapter_control);
25921256Syl150051 
25931256Syl150051 #ifdef  XGE_HAL_PROCESS_LINK_INT_IN_ISR
25941256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
25951256Syl150051 		/*
25961256Syl150051 		 * Mask the Link Down interrupt and unmask the Link up
25971256Syl150051 		 * interrupt
25981256Syl150051 		 */
25991256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
26001256Syl150051 					      &bar0->misc_int_mask);
26011256Syl150051 		val64 |= XGE_HAL_MISC_INT_REG_LINK_DOWN_INT;
26021256Syl150051 		val64 &= ~XGE_HAL_MISC_INT_REG_LINK_UP_INT;
26031256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
26041256Syl150051 				       &bar0->misc_int_mask);
26051256Syl150051 
26061256Syl150051 		/* link is down */
26071256Syl150051 		xge_debug_device(XGE_TRACE, "calling link down..");
26081256Syl150051 		hldev->link_state = XGE_HAL_LINK_DOWN;
26091256Syl150051 
26101256Syl150051 		/* notify ULD */
26111256Syl150051 		if (g_xge_hal_driver->uld_callbacks.link_down) {
26121256Syl150051 				g_xge_hal_driver->uld_callbacks.link_down(
26131256Syl150051 					hldev->upper_layer_info);
26141256Syl150051 		}
26151256Syl150051 		return 1;
26161256Syl150051 	}
26171256Syl150051 #endif
26181256Syl150051 	/* notify ULD */
26191256Syl150051 	(void) xge_queue_produce_context(hldev->queueh,
26206937Sxw161283 					 XGE_HAL_EVENT_LINK_IS_DOWN, hldev);
26211256Syl150051 	/* link is down */
26221256Syl150051 	return 1;
26231256Syl150051 }
26241256Syl150051 /*
26251256Syl150051  * __hal_device_handle_link_state_change
26261256Syl150051  * @hldev: HAL device handle.
26271256Syl150051  *
26281256Syl150051  * Link state change handler. The function is invoked by HAL when
26291256Syl150051  * Xframe indicates link state change condition. The code here makes sure to
26301256Syl150051  * 1) ignore redundant state change indications;
26311256Syl150051  * 2) execute link-up sequence, and handle the failure to bring the link up;
26321256Syl150051  * 3) generate XGE_HAL_LINK_UP/DOWN event for the subsequent handling by
26331256Syl150051  *    upper-layer driver (ULD).
26341256Syl150051  */
26351256Syl150051 static int
__hal_device_handle_link_state_change(xge_hal_device_t * hldev)26361256Syl150051 __hal_device_handle_link_state_change(xge_hal_device_t *hldev)
26371256Syl150051 {
26381256Syl150051 	u64 hw_status;
26391256Syl150051 	int hw_link_state;
26401256Syl150051 	int retcode;
26411256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
26421256Syl150051 	u64 val64;
26433115Syl150051 	int i = 0;
26441256Syl150051 
26451256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
26461256Syl150051 					&bar0->adapter_control);
26471256Syl150051 
26481256Syl150051 	/* If the adapter is not enabled but the hal thinks we are in the up
26491256Syl150051 	 * state then transition to the down state.
26501256Syl150051 	 */
26511256Syl150051 	if ( !(val64 & XGE_HAL_ADAPTER_CNTL_EN) &&
26521256Syl150051 	     (hldev->link_state == XGE_HAL_LINK_UP) ) {
26531256Syl150051 		return(__hal_device_handle_link_down_ind(hldev));
26541256Syl150051 	}
26551256Syl150051 
26563115Syl150051 	do {
26573115Syl150051 		xge_os_mdelay(1);
26583115Syl150051 		(void) xge_hal_device_status(hldev, &hw_status);
26593115Syl150051 		hw_link_state = (hw_status &
26603115Syl150051 			(XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
26613115Syl150051 				XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) ?
26623115Syl150051 				XGE_HAL_LINK_DOWN : XGE_HAL_LINK_UP;
26633115Syl150051 
26643115Syl150051 		/* check if the current link state is still considered
26653115Syl150051 		 * to be changed. This way we will make sure that this is
26663115Syl150051 		 * not a noise which needs to be filtered out */
26673115Syl150051 		if (hldev->link_state == hw_link_state)
26683115Syl150051 			break;
26693115Syl150051 	} while (i++ < hldev->config.link_valid_cnt);
26701256Syl150051 
26711256Syl150051 	/* If the current link state is same as previous, just return */
26721256Syl150051 	if (hldev->link_state == hw_link_state)
26731256Syl150051 		retcode = 0;
26741256Syl150051 	/* detected state change */
26751256Syl150051 	else if (hw_link_state == XGE_HAL_LINK_UP)
26761256Syl150051 		retcode = __hal_device_handle_link_up_ind(hldev);
26771256Syl150051 	else
26781256Syl150051 		retcode = __hal_device_handle_link_down_ind(hldev);
26791256Syl150051 	return retcode;
26801256Syl150051 }
26811256Syl150051 
26821256Syl150051 /*
26831256Syl150051  *
26841256Syl150051  */
26851256Syl150051 static void
__hal_device_handle_serr(xge_hal_device_t * hldev,char * reg,u64 value)26861256Syl150051 __hal_device_handle_serr(xge_hal_device_t *hldev, char *reg, u64 value)
26871256Syl150051 {
26881256Syl150051 	hldev->stats.sw_dev_err_stats.serr_cnt++;
26891256Syl150051 	if (hldev->config.dump_on_serr) {
26901256Syl150051 #ifdef XGE_HAL_USE_MGMT_AUX
26911256Syl150051 		(void) xge_hal_aux_device_dump(hldev);
26921256Syl150051 #endif
26931256Syl150051 	}
26941256Syl150051 
26951256Syl150051 	(void) xge_queue_produce(hldev->queueh, XGE_HAL_EVENT_SERR, hldev,
26961256Syl150051 			   1, sizeof(u64), (void *)&value);
26971256Syl150051 
26983115Syl150051 	xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg,
26991256Syl150051 				  (unsigned long long) value);
27001256Syl150051 }
27011256Syl150051 
27021256Syl150051 /*
27031256Syl150051  *
27041256Syl150051  */
27051256Syl150051 static void
__hal_device_handle_eccerr(xge_hal_device_t * hldev,char * reg,u64 value)27061256Syl150051 __hal_device_handle_eccerr(xge_hal_device_t *hldev, char *reg, u64 value)
27071256Syl150051 {
27081256Syl150051 	if (hldev->config.dump_on_eccerr) {
27091256Syl150051 #ifdef XGE_HAL_USE_MGMT_AUX
27101256Syl150051 		(void) xge_hal_aux_device_dump(hldev);
27111256Syl150051 #endif
27121256Syl150051 	}
27131256Syl150051 
27141256Syl150051 	/* Herc smart enough to recover on its own! */
27151256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) {
27161256Syl150051 		(void) xge_queue_produce(hldev->queueh,
27171256Syl150051 			XGE_HAL_EVENT_ECCERR, hldev,
27181256Syl150051 			1, sizeof(u64), (void *)&value);
27191256Syl150051 	}
27201256Syl150051 
27213115Syl150051         xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg,
27221256Syl150051                                   (unsigned long long) value);
27231256Syl150051 }
27241256Syl150051 
27251256Syl150051 /*
27261256Syl150051  *
27271256Syl150051  */
27281256Syl150051 static void
__hal_device_handle_parityerr(xge_hal_device_t * hldev,char * reg,u64 value)27291256Syl150051 __hal_device_handle_parityerr(xge_hal_device_t *hldev, char *reg, u64 value)
27301256Syl150051 {
27311256Syl150051 	if (hldev->config.dump_on_parityerr) {
27321256Syl150051 #ifdef XGE_HAL_USE_MGMT_AUX
27331256Syl150051 		(void) xge_hal_aux_device_dump(hldev);
27341256Syl150051 #endif
27351256Syl150051 	}
27361256Syl150051 	(void) xge_queue_produce_context(hldev->queueh,
27371256Syl150051 			XGE_HAL_EVENT_PARITYERR, hldev);
27381256Syl150051 
27393115Syl150051         xge_debug_device(XGE_ERR, "%s: read "XGE_OS_LLXFMT, reg,
27401256Syl150051                                   (unsigned long long) value);
27411256Syl150051 }
27421256Syl150051 
27431256Syl150051 /*
27441256Syl150051  *
27451256Syl150051  */
27461256Syl150051 static void
__hal_device_handle_targetabort(xge_hal_device_t * hldev)27471256Syl150051 __hal_device_handle_targetabort(xge_hal_device_t *hldev)
27481256Syl150051 {
27491256Syl150051 	(void) xge_queue_produce_context(hldev->queueh,
27501256Syl150051 			XGE_HAL_EVENT_TARGETABORT, hldev);
27511256Syl150051 }
27521256Syl150051 
27531256Syl150051 
27541256Syl150051 /*
27551256Syl150051  * __hal_device_hw_initialize
27561256Syl150051  * @hldev: HAL device handle.
27571256Syl150051  *
27581256Syl150051  * Initialize Xframe hardware.
27591256Syl150051  */
27601256Syl150051 static xge_hal_status_e
__hal_device_hw_initialize(xge_hal_device_t * hldev)27611256Syl150051 __hal_device_hw_initialize(xge_hal_device_t *hldev)
27621256Syl150051 {
27631256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
27641256Syl150051 	xge_hal_status_e status;
27651256Syl150051 	u64 val64;
27661256Syl150051 
27671256Syl150051 	/* Set proper endian settings and verify the same by reading the PIF
27681256Syl150051 	 * Feed-back register. */
27691256Syl150051 	status = __hal_device_set_swapper(hldev);
27701256Syl150051 	if (status != XGE_HAL_OK) {
27711256Syl150051 		return status;
27721256Syl150051 	}
27731256Syl150051 
27741256Syl150051 	/* update the pci mode, frequency, and width */
27751256Syl150051 	if (__hal_device_pci_info_get(hldev, &hldev->pci_mode,
27761256Syl150051 		&hldev->bus_frequency, &hldev->bus_width) != XGE_HAL_OK){
27771256Syl150051 		hldev->pci_mode	= XGE_HAL_PCI_INVALID_MODE;
27781256Syl150051 		hldev->bus_frequency = XGE_HAL_PCI_BUS_FREQUENCY_UNKNOWN;
27791256Syl150051 		hldev->bus_width = XGE_HAL_PCI_BUS_WIDTH_UNKNOWN;
27801256Syl150051 		/*
27811256Syl150051 		 * FIXME: this cannot happen.
27821256Syl150051 		 * But if it happens we cannot continue just like that
27831256Syl150051 		 */
27841256Syl150051 		xge_debug_device(XGE_ERR, "unable to get pci info");
27851256Syl150051 	}
27861256Syl150051 
27871256Syl150051 	if ((hldev->pci_mode == XGE_HAL_PCI_33MHZ_MODE) ||
27881256Syl150051 		(hldev->pci_mode == XGE_HAL_PCI_66MHZ_MODE) ||
27891256Syl150051 		(hldev->pci_mode == XGE_HAL_PCI_BASIC_MODE)) {
27901256Syl150051 		/* PCI optimization: set TxReqTimeOut
27911256Syl150051 		 * register (0x800+0x120) to 0x1ff or
27921256Syl150051 		 * something close to this.
27931256Syl150051 		 * Note: not to be used for PCI-X! */
27941256Syl150051 
27951256Syl150051 		val64 = XGE_HAL_TXREQTO_VAL(0x1FF);
27961256Syl150051 		val64 |= XGE_HAL_TXREQTO_EN;
27971256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
27981256Syl150051 				     &bar0->txreqtimeout);
27991256Syl150051 
28001256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL,
28011256Syl150051 				     &bar0->read_retry_delay);
28021256Syl150051 
28031256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0ULL,
28041256Syl150051 				     &bar0->write_retry_delay);
28051256Syl150051 
28061256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI mode");
28071256Syl150051 	}
28081256Syl150051 
28096937Sxw161283 	if (hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_266MHZ ||
28106937Sxw161283 	    hldev->bus_frequency == XGE_HAL_PCI_BUS_FREQUENCY_250MHZ) {
28116937Sxw161283 
28126937Sxw161283 		/* Optimizing for PCI-X 266/250 */
28136937Sxw161283 
28146937Sxw161283 		val64 = XGE_HAL_TXREQTO_VAL(0x7F);
28156937Sxw161283 		val64 |= XGE_HAL_TXREQTO_EN;
28166937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
28176937Sxw161283 				     &bar0->txreqtimeout);
28186937Sxw161283 
28196937Sxw161283 		xge_debug_device(XGE_TRACE, "%s", "optimizing for PCI-X 266/250 modes");
28206937Sxw161283 	}
28216937Sxw161283 
28226937Sxw161283 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
28236937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL,
28246937Sxw161283 				     &bar0->read_retry_delay);
28256937Sxw161283 
28266937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0x4000000000000ULL,
28276937Sxw161283 				     &bar0->write_retry_delay);
28286937Sxw161283 	}
28296937Sxw161283 
28303115Syl150051 	/* added this to set the no of bytes used to update lso_bytes_sent
28313115Syl150051 	   returned TxD0 */
28323115Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28333115Syl150051 				      &bar0->pic_control_2);
28346937Sxw161283 	val64 &= ~XGE_HAL_TXD_WRITE_BC(0x2);
28353115Syl150051 	val64 |= XGE_HAL_TXD_WRITE_BC(0x4);
28363115Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
28373115Syl150051 			       &bar0->pic_control_2);
28381256Syl150051 	/* added this to clear the EOI_RESET field while leaving XGXS_RESET
28391256Syl150051 	 * in reset, then a 1-second delay */
28401256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
28411256Syl150051 			XGE_HAL_SW_RESET_XGXS, &bar0->sw_reset);
28421256Syl150051 	xge_os_mdelay(1000);
28431256Syl150051 
28441256Syl150051 	/* Clear the XGXS_RESET field of the SW_RESET register in order to
28451256Syl150051 	 * release the XGXS from reset. Its reset value is 0xA5; write 0x00
28461256Syl150051 	 * to activate the XGXS. The core requires a minimum 500 us reset.*/
28471256Syl150051         xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, 0, &bar0->sw_reset);
28481256Syl150051 	(void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28491256Syl150051 				&bar0->sw_reset);
28501256Syl150051 	xge_os_mdelay(1);
28511256Syl150051 
28521256Syl150051 	/* read registers in all blocks */
28531256Syl150051 	(void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28541256Syl150051 				   &bar0->mac_int_mask);
28551256Syl150051 	(void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28561256Syl150051 				   &bar0->mc_int_mask);
28571256Syl150051 	(void) xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28581256Syl150051 				   &bar0->xgxs_int_mask);
28591256Syl150051 
28601256Syl150051 	/* set default MTU and steer based on length*/
28611256Syl150051 	__hal_ring_mtu_set(hldev, hldev->config.mtu+22); // Alway set 22 bytes extra for steering to work
28621256Syl150051 
28631256Syl150051 	if (hldev->config.mac.rmac_bcast_en) {
28641256Syl150051         xge_hal_device_bcast_enable(hldev);
28651256Syl150051 	} else {
28661256Syl150051 	    xge_hal_device_bcast_disable(hldev);
28671256Syl150051 	}
28681256Syl150051 
28691256Syl150051 #ifndef XGE_HAL_HERC_EMULATION
28701256Syl150051 	__hal_device_xaui_configure(hldev);
28711256Syl150051 #endif
28721256Syl150051 	__hal_device_mac_link_util_set(hldev);
28731256Syl150051 
28741256Syl150051 	__hal_device_mac_link_util_set(hldev);
28751256Syl150051 
28761256Syl150051 	/*
28771256Syl150051 	 * Keep its PCI REQ# line asserted during a write
28781256Syl150051 	 * transaction up to the end of the transaction
28791256Syl150051 	 */
28801256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28816937Sxw161283 				&bar0->misc_control);
28826937Sxw161283 
28831256Syl150051 	val64 |= XGE_HAL_MISC_CONTROL_EXT_REQ_EN;
28846937Sxw161283 
28851256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
28866937Sxw161283 				val64, &bar0->misc_control);
28876937Sxw161283 
28886937Sxw161283 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
28896937Sxw161283 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
28906937Sxw161283 					&bar0->misc_control);
28916937Sxw161283 
28926937Sxw161283 		val64 |= XGE_HAL_MISC_CONTROL_LINK_FAULT;
28936937Sxw161283 
28946937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
28956937Sxw161283 					val64, &bar0->misc_control);
28966937Sxw161283 	}
28971256Syl150051 
28981256Syl150051 	/*
28993115Syl150051 	 * bimodal interrupts is when all Rx traffic interrupts
29003115Syl150051 	 * will go to TTI, so we need to adjust RTI settings and
29013115Syl150051 	 * use adaptive TTI timer. We need to make sure RTI is
29023115Syl150051 	 * properly configured to sane value which will not
29033115Syl150051 	 * distrupt bimodal behavior.
29041256Syl150051 	 */
29053115Syl150051 	if (hldev->config.bimodal_interrupts) {
29063115Syl150051 		int i;
29073115Syl150051 
29083115Syl150051 		/* force polling_cnt to be "0", otherwise
29093115Syl150051 		 * IRQ workload statistics will be screwed. This could
29103115Syl150051 		 * be worked out in TXPIC handler later. */
29113115Syl150051 		hldev->config.isr_polling_cnt = 0;
29123115Syl150051 		hldev->config.sched_timer_us = 10000;
29133115Syl150051 
29143115Syl150051 		/* disable all TTI < 56 */
29153115Syl150051 		for (i=0; i<XGE_HAL_MAX_FIFO_NUM; i++) {
29163115Syl150051 			int j;
29173115Syl150051 			if (!hldev->config.fifo.queue[i].configured)
29183115Syl150051 				continue;
29193115Syl150051 			for (j=0; j<XGE_HAL_MAX_FIFO_TTI_NUM; j++) {
29203115Syl150051 			    if (hldev->config.fifo.queue[i].tti[j].enabled)
29213115Syl150051 				hldev->config.fifo.queue[i].tti[j].enabled = 0;
29223115Syl150051 			}
29231256Syl150051 		}
29243115Syl150051 
29253115Syl150051 		/* now configure bimodal interrupts */
29263115Syl150051 		__hal_device_bimodal_configure(hldev);
29273115Syl150051 	}
29283115Syl150051 
29293115Syl150051 	status = __hal_device_tti_configure(hldev, 0);
29303115Syl150051 	if (status != XGE_HAL_OK)
29313115Syl150051 		return status;
29321256Syl150051 
29331256Syl150051 	status = __hal_device_rti_configure(hldev, 0);
29343115Syl150051 	if (status != XGE_HAL_OK)
29351256Syl150051 		return status;
29363115Syl150051 
29371256Syl150051 	status = __hal_device_rth_it_configure(hldev);
29383115Syl150051 	if (status != XGE_HAL_OK)
29391256Syl150051 		return status;
29403115Syl150051 
29411256Syl150051 	status = __hal_device_rth_spdm_configure(hldev);
29423115Syl150051 	if (status != XGE_HAL_OK)
29431256Syl150051 		return status;
29443115Syl150051 
29451256Syl150051 	status = __hal_device_rts_mac_configure(hldev);
29461256Syl150051 	if (status != XGE_HAL_OK) {
29476937Sxw161283 		xge_debug_device(XGE_ERR, "__hal_device_rts_mac_configure Failed ");
29486937Sxw161283 		return status;
29496937Sxw161283 	}
29506937Sxw161283 
29516937Sxw161283 	status = __hal_device_rts_port_configure(hldev);
29526937Sxw161283 	if (status != XGE_HAL_OK) {
29536937Sxw161283 		xge_debug_device(XGE_ERR, "__hal_device_rts_port_configure Failed ");
29541256Syl150051 		return status;
29551256Syl150051 	}
29561256Syl150051 
29573115Syl150051 	status = __hal_device_rts_qos_configure(hldev);
29583115Syl150051 	if (status != XGE_HAL_OK) {
29596937Sxw161283 		xge_debug_device(XGE_ERR, "__hal_device_rts_qos_configure Failed ");
29603115Syl150051 		return status;
29613115Syl150051 	}
29623115Syl150051 
29631256Syl150051 	__hal_device_pause_frames_configure(hldev);
29641256Syl150051 	__hal_device_rmac_padding_configure(hldev);
29651256Syl150051 	__hal_device_shared_splits_configure(hldev);
29661256Syl150051 
29671256Syl150051 	/* make sure all interrupts going to be disabled at the moment */
29681256Syl150051 	__hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0);
29691256Syl150051 
29701256Syl150051 	/* SXE-008 Transmit DMA arbitration issue */
29711256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA &&
29721256Syl150051 	    hldev->revision < 4) {
29731256Syl150051 		xge_os_pio_mem_write64(hldev->pdev,hldev->regh0,
29741256Syl150051 				XGE_HAL_ADAPTER_PCC_ENABLE_FOUR,
29751256Syl150051 				&bar0->pcc_enable);
29761256Syl150051 	}
29771256Syl150051 	__hal_fifo_hw_initialize(hldev);
29781256Syl150051 	__hal_ring_hw_initialize(hldev);
29791256Syl150051 
29801256Syl150051 	if (__hal_device_wait_quiescent(hldev, &val64)) {
29811256Syl150051 		return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
29821256Syl150051 	}
29831256Syl150051 
29841256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1,
29851256Syl150051 		XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT,
29861256Syl150051 		 XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
29871256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!");
29881256Syl150051 		return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
29891256Syl150051 	}
29901256Syl150051 
29913115Syl150051 	xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is quiescent",
29921256Syl150051 			  (unsigned long long)(ulong_t)hldev);
29931256Syl150051 
29946937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX ||
29956937Sxw161283 	    hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI) {
29966937Sxw161283 		/*
29976937Sxw161283 		 * If MSI is enabled, ensure that One Shot for MSI in PCI_CTRL
29986937Sxw161283 		 * is disabled.
29996937Sxw161283 		 */
30006937Sxw161283 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
30016937Sxw161283 					    &bar0->pic_control);
30026937Sxw161283 		val64 &= ~(XGE_HAL_PIC_CNTL_ONE_SHOT_TINT);
30036937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
30046937Sxw161283 					    &bar0->pic_control);
30056937Sxw161283 	}
30061256Syl150051 
30071256Syl150051 	hldev->hw_is_initialized = 1;
30081256Syl150051 	hldev->terminating = 0;
30091256Syl150051 	return XGE_HAL_OK;
30101256Syl150051 }
30111256Syl150051 
30121256Syl150051 /*
30131256Syl150051  * __hal_device_reset - Reset device only.
30141256Syl150051  * @hldev: HAL device handle.
30151256Syl150051  *
30161256Syl150051  * Reset the device, and subsequently restore
30171256Syl150051  * the previously saved PCI configuration space.
30181256Syl150051  */
30193115Syl150051 #define XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT 50
30201256Syl150051 static xge_hal_status_e
__hal_device_reset(xge_hal_device_t * hldev)30211256Syl150051 __hal_device_reset(xge_hal_device_t *hldev)
30221256Syl150051 {
30231256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
30243115Syl150051 	int i, j, swap_done, pcisize = 0;
30251256Syl150051 	u64 val64, rawval = 0ULL;
30261256Syl150051 
30276937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) {
30286937Sxw161283 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
30296937Sxw161283 			if ( hldev->bar2 ) {
30306937Sxw161283 			    u64 *msix_vetor_table = (u64 *)hldev->bar2;
30316937Sxw161283 
30326937Sxw161283 			    // 2 64bit words for each entry
30336937Sxw161283 			    for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2;
30346937Sxw161283 			         i++) {
30356937Sxw161283 			          hldev->msix_vector_table[i] =
30366937Sxw161283 				       xge_os_pio_mem_read64(hldev->pdev,
30376937Sxw161283 			                  hldev->regh2, &msix_vetor_table[i]);
30386937Sxw161283 			    }
30391256Syl150051 			}
30401256Syl150051 		}
30411256Syl150051 	}
30421256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
30431256Syl150051 	                            &bar0->pif_rd_swapper_fb);
30441256Syl150051 	swap_done = (val64 == XGE_HAL_IF_RD_SWAPPER_FB);
30451256Syl150051 
30461256Syl150051 	if (swap_done) {
30471256Syl150051 		__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
30481256Syl150051 		     (u32)(XGE_HAL_SW_RESET_ALL>>32), (char *)&bar0->sw_reset);
30491256Syl150051 	} else {
30501256Syl150051 		u32 val = (u32)(XGE_HAL_SW_RESET_ALL >> 32);
30511256Syl150051 #if defined(XGE_OS_HOST_LITTLE_ENDIAN) || defined(XGE_OS_PIO_LITTLE_ENDIAN)
30521256Syl150051 		/* swap it */
30531256Syl150051 		val = (((val & (u32)0x000000ffUL) << 24) |
30541256Syl150051 		       ((val & (u32)0x0000ff00UL) <<  8) |
30551256Syl150051 		       ((val & (u32)0x00ff0000UL) >>  8) |
30561256Syl150051 		       ((val & (u32)0xff000000UL) >> 24));
30571256Syl150051 #endif
30581256Syl150051 		xge_os_pio_mem_write32(hldev->pdev, hldev->regh0, val,
30591256Syl150051 				     &bar0->sw_reset);
30601256Syl150051 	}
30611256Syl150051 
30623115Syl150051 	pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)?
30633115Syl150051 			   XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA;
30643115Syl150051 
30653115Syl150051 	xge_os_mdelay(20); /* Wait for 20 ms after reset */
30663115Syl150051 
30673115Syl150051 	{
30683115Syl150051 		/* Poll for no more than 1 second */
30693115Syl150051 		for (i = 0; i < XGE_HAL_MAX_PCI_CONFIG_SPACE_REINIT; i++)
30703115Syl150051 		{
30713115Syl150051 			for (j = 0; j < pcisize; j++) {
30723115Syl150051 				xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4,
30733115Syl150051 					*((u32*)&hldev->pci_config_space + j));
30743115Syl150051 			}
30753115Syl150051 
30763115Syl150051 			xge_os_pci_read16(hldev->pdev,hldev->cfgh,
30773115Syl150051 				xge_offsetof(xge_hal_pci_config_le_t, device_id),
30783115Syl150051 				&hldev->device_id);
30796937Sxw161283 
30803115Syl150051 			if (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_UNKNOWN)
30813115Syl150051 				break;
30823115Syl150051 			xge_os_mdelay(20);
30833115Syl150051 		}
30843115Syl150051 	}
30853115Syl150051 
30863115Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_UNKNOWN)
30873115Syl150051 	{
30883115Syl150051 		xge_debug_device(XGE_ERR, "device reset failed");
30893115Syl150051 			return XGE_HAL_ERR_RESET_FAILED;
30903115Syl150051 	}
30913115Syl150051 
30921256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
30931256Syl150051 		int cnt = 0;
30941256Syl150051 
30951256Syl150051 		rawval = XGE_HAL_SW_RESET_RAW_VAL_HERC;
30961256Syl150051 		pcisize = XGE_HAL_PCISIZE_HERC;
30971256Syl150051 		xge_os_mdelay(1);
30981256Syl150051 		do {
30991256Syl150051 			val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
31001256Syl150051 				&bar0->sw_reset);
31011256Syl150051 			if (val64 != rawval) {
31021256Syl150051 				break;
31031256Syl150051 			}
31041256Syl150051 			cnt++;
31051256Syl150051 			xge_os_mdelay(1); /* Wait for 1ms before retry */
31061256Syl150051 		} while(cnt < 20);
31071256Syl150051 	} else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) {
31081256Syl150051 		rawval = XGE_HAL_SW_RESET_RAW_VAL_XENA;
31091256Syl150051 		pcisize = XGE_HAL_PCISIZE_XENA;
31101256Syl150051 		xge_os_mdelay(XGE_HAL_DEVICE_RESET_WAIT_MAX_MILLIS);
31111256Syl150051 	}
31121256Syl150051 
31131256Syl150051 	/* Restore MSI-X vector table */
31146937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) {
31156937Sxw161283 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
31166937Sxw161283 			if ( hldev->bar2 ) {
31176937Sxw161283 			    /*
31186937Sxw161283 			     * 94: MSIXTable 00000004  ( BIR:4  Offset:0x0 )
31196937Sxw161283 			     * 98: PBATable  00000404  ( BIR:4  Offset:0x400 )
31206937Sxw161283 			     */
31216937Sxw161283 			     u64 *msix_vetor_table = (u64 *)hldev->bar2;
31226937Sxw161283 
31236937Sxw161283 			     /* 2 64bit words for each entry */
31246937Sxw161283 			     for (i = 0; i < XGE_HAL_MAX_MSIX_MESSAGES * 2;
31256937Sxw161283 				  i++) {
31266937Sxw161283 			         xge_os_pio_mem_write64(hldev->pdev,
31276937Sxw161283 					hldev->regh2,
31286937Sxw161283 					hldev->msix_vector_table[i],
31296937Sxw161283 					&msix_vetor_table[i]);
31306937Sxw161283 			     }
31311256Syl150051 			}
31321256Syl150051 		}
31331256Syl150051 	}
31341256Syl150051 
31351256Syl150051 	hldev->link_state = XGE_HAL_LINK_DOWN;
31361256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
31371256Syl150051                                       &bar0->sw_reset);
31381256Syl150051 
31391256Syl150051 	if (val64 != rawval) {
31401256Syl150051 		xge_debug_device(XGE_ERR, "device has not been reset "
31413115Syl150051 			"got 0x"XGE_OS_LLXFMT", expected 0x"XGE_OS_LLXFMT,
31421256Syl150051 			(unsigned long long)val64, (unsigned long long)rawval);
31431256Syl150051 	        return XGE_HAL_ERR_RESET_FAILED;
31441256Syl150051 	}
31451256Syl150051 
31461256Syl150051 	hldev->hw_is_initialized = 0;
31471256Syl150051 	return XGE_HAL_OK;
31481256Syl150051 }
31491256Syl150051 
31501256Syl150051 /*
31511256Syl150051  * __hal_device_poll - General private routine to poll the device.
31521256Syl150051  * @hldev: HAL device handle.
31531256Syl150051  *
31541256Syl150051  * Returns: one of the xge_hal_status_e{} enumerated types.
31551256Syl150051  * XGE_HAL_OK			- for success.
31561256Syl150051  * XGE_HAL_ERR_CRITICAL         - when encounters critical error.
31571256Syl150051  */
31581256Syl150051 static xge_hal_status_e
__hal_device_poll(xge_hal_device_t * hldev)31591256Syl150051 __hal_device_poll(xge_hal_device_t *hldev)
31601256Syl150051 {
31611256Syl150051 	xge_hal_pci_bar0_t *bar0;
31621256Syl150051 	u64 err_reg;
31631256Syl150051 
31641256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
31651256Syl150051 
31661256Syl150051 	/* Handling SERR errors by forcing a H/W reset. */
31671256Syl150051 	err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
31681256Syl150051 				      &bar0->serr_source);
31691256Syl150051 	if (err_reg & XGE_HAL_SERR_SOURCE_ANY) {
31701256Syl150051 		__hal_device_handle_serr(hldev, "serr_source", err_reg);
31711256Syl150051 		return XGE_HAL_ERR_CRITICAL;
31721256Syl150051 	}
31731256Syl150051 
31741256Syl150051 	err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
31751256Syl150051 					&bar0->misc_int_reg);
31761256Syl150051 
31771256Syl150051 	if (err_reg & XGE_HAL_MISC_INT_REG_DP_ERR_INT) {
31781256Syl150051 		hldev->stats.sw_dev_err_stats.parity_err_cnt++;
31791256Syl150051 		__hal_device_handle_parityerr(hldev, "misc_int_reg", err_reg);
31801256Syl150051 		return XGE_HAL_ERR_CRITICAL;
31811256Syl150051 	}
31821256Syl150051 
31831256Syl150051 #ifdef  XGE_HAL_PROCESS_LINK_INT_IN_ISR
31846937Sxw161283 	if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) ||
31856937Sxw161283 		(hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX))
31861256Syl150051 #endif
31871256Syl150051 	{
31881256Syl150051 
31891256Syl150051 		/* Handling link status change error Intr */
31901256Syl150051 		err_reg = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
31911256Syl150051 						&bar0->mac_rmac_err_reg);
31921256Syl150051 		if (__hal_device_handle_link_state_change(hldev))
31931256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
31941256Syl150051 				       err_reg, &bar0->mac_rmac_err_reg);
31951256Syl150051 	}
31961256Syl150051 
31971256Syl150051 	if (hldev->inject_serr != 0) {
31981256Syl150051 		err_reg = hldev->inject_serr;
31991256Syl150051 		hldev->inject_serr = 0;
32001256Syl150051 		__hal_device_handle_serr(hldev, "inject_serr", err_reg);
32011256Syl150051 		return XGE_HAL_ERR_CRITICAL;
32021256Syl150051         }
32031256Syl150051 
32041256Syl150051         if (hldev->inject_ecc != 0) {
32051256Syl150051                 err_reg = hldev->inject_ecc;
32061256Syl150051                 hldev->inject_ecc = 0;
32071256Syl150051 		hldev->stats.sw_dev_err_stats.ecc_err_cnt++;
32081256Syl150051                 __hal_device_handle_eccerr(hldev, "inject_ecc", err_reg);
32091256Syl150051 		return XGE_HAL_ERR_CRITICAL;
32101256Syl150051         }
32111256Syl150051 
32121256Syl150051 	if (hldev->inject_bad_tcode != 0) {
32131256Syl150051 		u8 t_code = hldev->inject_bad_tcode;
32141256Syl150051 		xge_hal_channel_t channel;
32151256Syl150051 		xge_hal_fifo_txd_t txd;
32161256Syl150051 		xge_hal_ring_rxd_1_t rxd;
32171256Syl150051 
32181256Syl150051 		channel.devh =  hldev;
32191256Syl150051 
32201256Syl150051 		if (hldev->inject_bad_tcode_for_chan_type ==
32211256Syl150051 						XGE_HAL_CHANNEL_TYPE_FIFO) {
32221256Syl150051 			channel.type = XGE_HAL_CHANNEL_TYPE_FIFO;
32231256Syl150051 
32241256Syl150051 		} else {
32251256Syl150051 			channel.type = XGE_HAL_CHANNEL_TYPE_RING;
32261256Syl150051 		}
32271256Syl150051 
32281256Syl150051                 hldev->inject_bad_tcode = 0;
32291256Syl150051 
32301256Syl150051 		if (channel.type == XGE_HAL_CHANNEL_TYPE_FIFO)
32311256Syl150051 			return xge_hal_device_handle_tcode(&channel, &txd,
32321256Syl150051 			                                   t_code);
32331256Syl150051 		else
32341256Syl150051 			return xge_hal_device_handle_tcode(&channel, &rxd,
32351256Syl150051 			                                   t_code);
32361256Syl150051         }
32371256Syl150051 
32381256Syl150051 	return XGE_HAL_OK;
32391256Syl150051 }
32401256Syl150051 
32411256Syl150051 /*
32421256Syl150051  * __hal_verify_pcc_idle - Verify All Enbled PCC are IDLE or not
32431256Syl150051  * @hldev: HAL device handle.
32441256Syl150051  * @adp_status: Adapter Status value
32451256Syl150051  * Usage: See xge_hal_device_enable{}.
32461256Syl150051  */
32471256Syl150051 xge_hal_status_e
__hal_verify_pcc_idle(xge_hal_device_t * hldev,u64 adp_status)32481256Syl150051 __hal_verify_pcc_idle(xge_hal_device_t *hldev, u64 adp_status)
32491256Syl150051 {
32501256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA &&
32511256Syl150051 	    hldev->revision < 4) {
32521256Syl150051 		/*
32531256Syl150051 		 * For Xena 1,2,3 we enable only 4 PCCs Due to
32541256Syl150051 		 * SXE-008 (Transmit DMA arbitration issue)
32551256Syl150051 		 */
32561256Syl150051 		if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE)
32571256Syl150051 			!= XGE_HAL_ADAPTER_STATUS_RMAC_PCC_4_IDLE) {
32581256Syl150051 			xge_debug_device(XGE_TRACE, "%s",
32591256Syl150051 			    "PCC is not IDLE after adapter enabled!");
32601256Syl150051 			return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
32611256Syl150051 		}
32621256Syl150051 	} else {
32631256Syl150051 		if ((adp_status & XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) !=
32641256Syl150051 			XGE_HAL_ADAPTER_STATUS_RMAC_PCC_IDLE) {
32651256Syl150051 			xge_debug_device(XGE_TRACE, "%s",
32661256Syl150051 			"PCC is not IDLE after adapter enabled!");
32671256Syl150051 			return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
32681256Syl150051 		}
32691256Syl150051 	}
32701256Syl150051 	return XGE_HAL_OK;
32711256Syl150051 }
32721256Syl150051 
32731256Syl150051 static void
__hal_update_bimodal(xge_hal_device_t * hldev,int ring_no)32743115Syl150051 __hal_update_bimodal(xge_hal_device_t *hldev, int ring_no)
32753115Syl150051 {
32763115Syl150051 	int tval, d, iwl_avg, len_avg, bytes_avg, bytes_hist, d_hist;
32773115Syl150051 	int iwl_rxcnt, iwl_txcnt, iwl_txavg, len_rxavg, iwl_rxavg, len_txavg;
32783115Syl150051 	int iwl_cnt, i;
32793115Syl150051 
32803115Syl150051 #define _HIST_SIZE	50 /* 0.5 sec history */
32813115Syl150051 #define _HIST_ADJ_TIMER	1
32823115Syl150051 #define _STEP		2
32833115Syl150051 
32843115Syl150051 	static int bytes_avg_history[_HIST_SIZE] = {0};
32853115Syl150051 	static int d_avg_history[_HIST_SIZE] = {0};
32863115Syl150051 	static int history_idx = 0;
32873115Syl150051 	static int pstep = 1;
32883115Syl150051 	static int hist_adj_timer = 0;
32893115Syl150051 
32903115Syl150051 	/*
32913115Syl150051 	 * tval - current value of this bimodal timer
32923115Syl150051 	 */
32933115Syl150051 	tval = hldev->bimodal_tti[ring_no].timer_val_us;
32943115Syl150051 
32953115Syl150051 	/*
32963115Syl150051 	 * d - how many interrupts we were getting since last
32973115Syl150051 	 *     bimodal timer tick.
32983115Syl150051 	 */
32993115Syl150051 	d = hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt -
33003115Syl150051 		hldev->bimodal_intr_cnt;
33013115Syl150051 
33023115Syl150051 	/* advance bimodal interrupt counter */
33033115Syl150051 	hldev->bimodal_intr_cnt =
33043115Syl150051 		hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt;
33053115Syl150051 
33063115Syl150051 	/*
33073115Syl150051 	 * iwl_cnt - how many interrupts we've got since last
33083115Syl150051 	 *           bimodal timer tick.
33093115Syl150051 	 */
33103115Syl150051 	iwl_rxcnt = (hldev->irq_workload_rxcnt[ring_no] ?
33113115Syl150051                      hldev->irq_workload_rxcnt[ring_no] : 1);
33123115Syl150051 	iwl_txcnt = (hldev->irq_workload_txcnt[ring_no] ?
33133115Syl150051                      hldev->irq_workload_txcnt[ring_no] : 1);
33143115Syl150051 	iwl_cnt = iwl_rxcnt + iwl_txcnt;
33153115Syl150051 	iwl_cnt = iwl_cnt; /* just to remove the lint warning */
33163115Syl150051 
33173115Syl150051 	/*
33183115Syl150051 	 * we need to take hldev->config.isr_polling_cnt into account
33193115Syl150051 	 * but for some reason this line causing GCC to produce wrong
33203115Syl150051 	 * code on Solaris. As of now, if bimodal_interrupts is configured
33213115Syl150051 	 * hldev->config.isr_polling_cnt is forced to be "0".
33223115Syl150051 	 *
33233115Syl150051 	 * iwl_cnt = iwl_cnt / (hldev->config.isr_polling_cnt + 1); */
33243115Syl150051 
33253115Syl150051 	/*
33263115Syl150051 	 * iwl_avg - how many RXDs on avarage been processed since
33273115Syl150051 	 *           last bimodal timer tick. This indirectly includes
33283115Syl150051 	 *           CPU utilizations.
33293115Syl150051 	 */
33303115Syl150051 	iwl_rxavg = hldev->irq_workload_rxd[ring_no] / iwl_rxcnt;
33313115Syl150051 	iwl_txavg = hldev->irq_workload_txd[ring_no] / iwl_txcnt;
33323115Syl150051 	iwl_avg = iwl_rxavg + iwl_txavg;
33333115Syl150051 	iwl_avg = iwl_avg == 0 ? 1 : iwl_avg;
33343115Syl150051 
33353115Syl150051 	/*
33363115Syl150051 	 * len_avg - how many bytes on avarage been processed since
33373115Syl150051 	 *           last bimodal timer tick. i.e. avarage frame size.
33383115Syl150051 	 */
33393115Syl150051 	len_rxavg = 1 + hldev->irq_workload_rxlen[ring_no] /
33403115Syl150051 		       (hldev->irq_workload_rxd[ring_no] ?
33413115Syl150051 		        hldev->irq_workload_rxd[ring_no] : 1);
33423115Syl150051 	len_txavg = 1 + hldev->irq_workload_txlen[ring_no] /
33433115Syl150051 		       (hldev->irq_workload_txd[ring_no] ?
33443115Syl150051 		        hldev->irq_workload_txd[ring_no] : 1);
33453115Syl150051 	len_avg = len_rxavg + len_txavg;
33463115Syl150051 	if (len_avg < 60)
33473115Syl150051 		len_avg = 60;
33483115Syl150051 
33493115Syl150051 	/* align on low boundary */
33503115Syl150051 	if ((tval -_STEP) < hldev->config.bimodal_timer_lo_us)
33513115Syl150051 		tval = hldev->config.bimodal_timer_lo_us;
33523115Syl150051 
33533115Syl150051 	/* reset faster */
33543115Syl150051 	if (iwl_avg == 1) {
33553115Syl150051 		tval = hldev->config.bimodal_timer_lo_us;
33563115Syl150051 		/* reset history */
33573115Syl150051 		for (i = 0; i < _HIST_SIZE; i++)
33583115Syl150051 			bytes_avg_history[i] = d_avg_history[i] = 0;
33593115Syl150051 		history_idx = 0;
33603115Syl150051 		pstep = 1;
33613115Syl150051 		hist_adj_timer = 0;
33623115Syl150051 	}
33633115Syl150051 
33643115Syl150051 	/* always try to ajust timer to the best throughput value */
33653115Syl150051 	bytes_avg = iwl_avg * len_avg;
33663115Syl150051 	history_idx %= _HIST_SIZE;
33673115Syl150051 	bytes_avg_history[history_idx] = bytes_avg;
33683115Syl150051 	d_avg_history[history_idx] = d;
33693115Syl150051 	history_idx++;
33703115Syl150051 	d_hist = bytes_hist = 0;
33713115Syl150051 	for (i = 0; i < _HIST_SIZE; i++) {
33723115Syl150051 		/* do not re-configure until history is gathered */
33733115Syl150051 		if (!bytes_avg_history[i]) {
33743115Syl150051 			tval = hldev->config.bimodal_timer_lo_us;
33753115Syl150051 			goto _end;
33763115Syl150051 		}
33773115Syl150051 		bytes_hist += bytes_avg_history[i];
33783115Syl150051 		d_hist += d_avg_history[i];
33793115Syl150051 	}
33803115Syl150051 	bytes_hist /= _HIST_SIZE;
33813115Syl150051 	d_hist /= _HIST_SIZE;
33823115Syl150051 
33833115Syl150051 //	xge_os_printf("d %d iwl_avg %d len_avg %d:%d:%d tval %d avg %d hist %d pstep %d",
33843115Syl150051 //		      d, iwl_avg, len_txavg, len_rxavg, len_avg, tval, d*bytes_avg,
33853115Syl150051 //		      d_hist*bytes_hist, pstep);
33863115Syl150051 
33873115Syl150051 	/* make an adaptive step */
33883115Syl150051 	if (d * bytes_avg < d_hist * bytes_hist && hist_adj_timer++ > _HIST_ADJ_TIMER) {
33893115Syl150051 		pstep = !pstep;
33903115Syl150051 		hist_adj_timer = 0;
33913115Syl150051 	}
33923115Syl150051 
33933115Syl150051 	if (pstep &&
33943115Syl150051 	    (tval + _STEP) <= hldev->config.bimodal_timer_hi_us) {
33953115Syl150051 		tval += _STEP;
33963115Syl150051 		hldev->stats.sw_dev_info_stats.bimodal_hi_adjust_cnt++;
33973115Syl150051 	} else if ((tval - _STEP) >= hldev->config.bimodal_timer_lo_us) {
33983115Syl150051 		tval -= _STEP;
33993115Syl150051 		hldev->stats.sw_dev_info_stats.bimodal_lo_adjust_cnt++;
34003115Syl150051 	}
34013115Syl150051 
34023115Syl150051 	/* enable TTI range A for better latencies */
34033115Syl150051 	hldev->bimodal_urange_a_en = 0;
34043115Syl150051 	if (tval <= hldev->config.bimodal_timer_lo_us && iwl_avg > 2)
34053115Syl150051 		hldev->bimodal_urange_a_en = 1;
34063115Syl150051 
34073115Syl150051 _end:
34083115Syl150051 	/* reset workload statistics counters */
34093115Syl150051 	hldev->irq_workload_rxcnt[ring_no] = 0;
34103115Syl150051 	hldev->irq_workload_rxd[ring_no] = 0;
34113115Syl150051 	hldev->irq_workload_rxlen[ring_no] = 0;
34123115Syl150051 	hldev->irq_workload_txcnt[ring_no] = 0;
34133115Syl150051 	hldev->irq_workload_txd[ring_no] = 0;
34143115Syl150051 	hldev->irq_workload_txlen[ring_no] = 0;
34153115Syl150051 
34163115Syl150051 	/* reconfigure TTI56 + ring_no with new timer value */
34173115Syl150051 	hldev->bimodal_timer_val_us = tval;
34183115Syl150051 	(void) __hal_device_rti_configure(hldev, 1);
34193115Syl150051 }
34203115Syl150051 
34213115Syl150051 static void
__hal_update_rxufca(xge_hal_device_t * hldev,int ring_no)34221256Syl150051 __hal_update_rxufca(xge_hal_device_t *hldev, int ring_no)
34231256Syl150051 {
34243115Syl150051 	int ufc, ic, i;
34253115Syl150051 
34263115Syl150051 	ufc = hldev->config.ring.queue[ring_no].rti.ufc_a;
34273115Syl150051 	ic = hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt;
34281256Syl150051 
34291256Syl150051 	/* urange_a adaptive coalescing */
34301256Syl150051 	if (hldev->rxufca_lbolt > hldev->rxufca_lbolt_time) {
34311256Syl150051 		if (ic > hldev->rxufca_intr_thres) {
34321256Syl150051 			if (ufc < hldev->config.rxufca_hi_lim) {
34331256Syl150051 				ufc += 1;
34341256Syl150051 				for (i=0; i<XGE_HAL_MAX_RING_NUM; i++)
34351256Syl150051 				   hldev->config.ring.queue[i].rti.ufc_a = ufc;
34361256Syl150051 				(void) __hal_device_rti_configure(hldev, 1);
34376937Sxw161283 				hldev->stats.sw_dev_info_stats.rxufca_hi_adjust_cnt++;
34381256Syl150051 			}
34391256Syl150051 			hldev->rxufca_intr_thres = ic +
34401256Syl150051 				hldev->config.rxufca_intr_thres; /* def: 30 */
34411256Syl150051 		} else {
34421256Syl150051 			if (ufc > hldev->config.rxufca_lo_lim) {
34431256Syl150051 				ufc -= 1;
34441256Syl150051 				for (i=0; i<XGE_HAL_MAX_RING_NUM; i++)
34451256Syl150051 				   hldev->config.ring.queue[i].rti.ufc_a = ufc;
34461256Syl150051 				(void) __hal_device_rti_configure(hldev, 1);
34476937Sxw161283 				hldev->stats.sw_dev_info_stats.rxufca_lo_adjust_cnt++;
34481256Syl150051 			}
34491256Syl150051 		}
34501256Syl150051 		hldev->rxufca_lbolt_time = hldev->rxufca_lbolt +
34511256Syl150051 			hldev->config.rxufca_lbolt_period;
34521256Syl150051 	}
34531256Syl150051 	hldev->rxufca_lbolt++;
34541256Syl150051 }
34551256Syl150051 
34561256Syl150051 /*
34571256Syl150051  * __hal_device_handle_mc - Handle MC interrupt reason
34581256Syl150051  * @hldev: HAL device handle.
34591256Syl150051  * @reason: interrupt reason
34601256Syl150051  */
34611256Syl150051 xge_hal_status_e
__hal_device_handle_mc(xge_hal_device_t * hldev,u64 reason)34621256Syl150051 __hal_device_handle_mc(xge_hal_device_t *hldev, u64 reason)
34631256Syl150051 {
34641256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
34651256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
34661256Syl150051 	u64 val64;
34671256Syl150051 
34681256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
34691256Syl150051 				&isrbar0->mc_int_status);
34701256Syl150051 	if (!(val64 & XGE_HAL_MC_INT_STATUS_MC_INT))
34711256Syl150051 		return XGE_HAL_OK;
34721256Syl150051 
34731256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
34741256Syl150051 				&isrbar0->mc_err_reg);
34751256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
34761256Syl150051 				val64, &isrbar0->mc_err_reg);
34771256Syl150051 
34781256Syl150051 	if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_L ||
34791256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_SG_ERR_U ||
34801256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_0 ||
34811256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_SG_ERR_1 ||
34821256Syl150051 	    (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA &&
34831256Syl150051 	     (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_L ||
34841256Syl150051 	      val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_SG_ERR_U ||
34851256Syl150051 	      val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_L ||
34861256Syl150051 	      val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_SG_ERR_U))) {
34871256Syl150051 		hldev->stats.sw_dev_err_stats.single_ecc_err_cnt++;
34881256Syl150051 		hldev->stats.sw_dev_err_stats.ecc_err_cnt++;
34891256Syl150051 	}
34901256Syl150051 
34911256Syl150051 	if (val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_L ||
34921256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_ETQ_ECC_DB_ERR_U ||
34931256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 ||
34941256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1 ||
34951256Syl150051 	    (xge_hal_device_check_id(hldev) != XGE_HAL_CARD_XENA &&
34961256Syl150051 	     (val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_L ||
34971256Syl150051 	      val64 & XGE_HAL_MC_ERR_REG_ITQ_ECC_DB_ERR_U ||
34981256Syl150051 	      val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_L ||
34991256Syl150051 	      val64 & XGE_HAL_MC_ERR_REG_RLD_ECC_DB_ERR_U))) {
35001256Syl150051 		hldev->stats.sw_dev_err_stats.double_ecc_err_cnt++;
35011256Syl150051 		hldev->stats.sw_dev_err_stats.ecc_err_cnt++;
35021256Syl150051 	}
35031256Syl150051 
35041256Syl150051 	if (val64 & XGE_HAL_MC_ERR_REG_SM_ERR) {
35051256Syl150051 		hldev->stats.sw_dev_err_stats.sm_err_cnt++;
35061256Syl150051 	}
35071256Syl150051 
35081256Syl150051 	/* those two should result in device reset */
35091256Syl150051 	if (val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_0 ||
35101256Syl150051 	    val64 & XGE_HAL_MC_ERR_REG_MIRI_ECC_DB_ERR_1) {
35111256Syl150051                 __hal_device_handle_eccerr(hldev, "mc_err_reg", val64);
35121256Syl150051 		return XGE_HAL_ERR_CRITICAL;
35131256Syl150051 	}
35141256Syl150051 
35151256Syl150051 	return XGE_HAL_OK;
35161256Syl150051 }
35171256Syl150051 
35181256Syl150051 /*
35191256Syl150051  * __hal_device_handle_pic - Handle non-traffic PIC interrupt reason
35201256Syl150051  * @hldev: HAL device handle.
35211256Syl150051  * @reason: interrupt reason
35221256Syl150051  */
35231256Syl150051 xge_hal_status_e
__hal_device_handle_pic(xge_hal_device_t * hldev,u64 reason)35241256Syl150051 __hal_device_handle_pic(xge_hal_device_t *hldev, u64 reason)
35251256Syl150051 {
35261256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
35271256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
35281256Syl150051 	u64 val64;
35291256Syl150051 
35301256Syl150051 	if (reason & XGE_HAL_PIC_INT_FLSH) {
35311256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
35321256Syl150051 					&isrbar0->flsh_int_reg);
35331256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
35341256Syl150051 				       val64, &isrbar0->flsh_int_reg);
35351256Syl150051 		/* FIXME: handle register */
35361256Syl150051 	}
35371256Syl150051 	if (reason & XGE_HAL_PIC_INT_MDIO) {
35381256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
35391256Syl150051 					&isrbar0->mdio_int_reg);
35401256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
35411256Syl150051 				       val64, &isrbar0->mdio_int_reg);
35421256Syl150051 		/* FIXME: handle register */
35431256Syl150051 	}
35441256Syl150051 	if (reason & XGE_HAL_PIC_INT_IIC) {
35451256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
35461256Syl150051 					&isrbar0->iic_int_reg);
35471256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
35481256Syl150051 				       val64, &isrbar0->iic_int_reg);
35491256Syl150051 		/* FIXME: handle register */
35501256Syl150051 	}
35511256Syl150051 	if (reason & XGE_HAL_PIC_INT_MISC) {
35521256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev,
35531256Syl150051 				hldev->regh0, &isrbar0->misc_int_reg);
35541256Syl150051 #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR
35556937Sxw161283 		if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) &&
35566937Sxw161283 			(hldev->config.intr_mode != XGE_HAL_INTR_MODE_MSIX)) {
35571256Syl150051 			/*  Check for Link interrupts. If both Link Up/Down
35581256Syl150051 			 *  bits are set, clear both and check adapter status
35591256Syl150051 			 */
35601256Syl150051 			if ((val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) &&
35611256Syl150051 			    (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT)) {
35621256Syl150051 				u64 temp64;
35631256Syl150051 
35641256Syl150051 				xge_debug_device(XGE_TRACE,
35653115Syl150051 				"both link up and link down detected "XGE_OS_LLXFMT,
35661256Syl150051 				(unsigned long long)val64);
35671256Syl150051 
35681256Syl150051 				temp64 = (XGE_HAL_MISC_INT_REG_LINK_DOWN_INT |
35691256Syl150051 					  XGE_HAL_MISC_INT_REG_LINK_UP_INT);
35701256Syl150051 				xge_os_pio_mem_write64(hldev->pdev,
35711256Syl150051 						       hldev->regh0, temp64,
35721256Syl150051 						       &isrbar0->misc_int_reg);
35731256Syl150051 			}
35741256Syl150051 			else if (val64 & XGE_HAL_MISC_INT_REG_LINK_UP_INT) {
35751256Syl150051 				xge_debug_device(XGE_TRACE,
35763115Syl150051 					"link up call request, misc_int "XGE_OS_LLXFMT,
35771256Syl150051 					(unsigned long long)val64);
35781256Syl150051 				__hal_device_handle_link_up_ind(hldev);
35791256Syl150051 			}
35801256Syl150051 			else if (val64 & XGE_HAL_MISC_INT_REG_LINK_DOWN_INT){
35811256Syl150051 				xge_debug_device(XGE_TRACE,
35823115Syl150051 					"link down request, misc_int "XGE_OS_LLXFMT,
35831256Syl150051 					(unsigned long long)val64);
35841256Syl150051 				__hal_device_handle_link_down_ind(hldev);
35851256Syl150051 			}
35861256Syl150051 		} else
35871256Syl150051 #endif
35881256Syl150051 		{
35891256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
35901256Syl150051 				       val64, &isrbar0->misc_int_reg);
35911256Syl150051 		}
35921256Syl150051 	}
35931256Syl150051 
35941256Syl150051 	return XGE_HAL_OK;
35951256Syl150051 }
35961256Syl150051 
35971256Syl150051 /*
35981256Syl150051  * __hal_device_handle_txpic - Handle TxPIC interrupt reason
35991256Syl150051  * @hldev: HAL device handle.
36001256Syl150051  * @reason: interrupt reason
36011256Syl150051  */
36021256Syl150051 xge_hal_status_e
__hal_device_handle_txpic(xge_hal_device_t * hldev,u64 reason)36031256Syl150051 __hal_device_handle_txpic(xge_hal_device_t *hldev, u64 reason)
36041256Syl150051 {
36051256Syl150051 	xge_hal_status_e status = XGE_HAL_OK;
36061256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
36071256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
36081256Syl150051 	volatile u64 val64;
36091256Syl150051 
36101256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
36111256Syl150051 				&isrbar0->pic_int_status);
36121256Syl150051 	if ( val64 & (XGE_HAL_PIC_INT_FLSH |
36131256Syl150051 		      XGE_HAL_PIC_INT_MDIO |
36141256Syl150051 		      XGE_HAL_PIC_INT_IIC |
36151256Syl150051 		      XGE_HAL_PIC_INT_MISC) ) {
36161256Syl150051 		status =  __hal_device_handle_pic(hldev, val64);
36171256Syl150051 		xge_os_wmb();
36181256Syl150051 	}
36191256Syl150051 
36201256Syl150051 	if (!(val64 & XGE_HAL_PIC_INT_TX))
36211256Syl150051 		return status;
36221256Syl150051 
36231256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
36241256Syl150051 				&isrbar0->txpic_int_reg);
36251256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
36261256Syl150051 			       val64, &isrbar0->txpic_int_reg);
36271256Syl150051 	xge_os_wmb();
36281256Syl150051 
36291256Syl150051 	if (val64 & XGE_HAL_TXPIC_INT_SCHED_INTR) {
36301256Syl150051 		int i;
36311256Syl150051 
36321256Syl150051 		if (g_xge_hal_driver->uld_callbacks.sched_timer != NULL)
36331256Syl150051 			g_xge_hal_driver->uld_callbacks.sched_timer(
36341256Syl150051 					  hldev, hldev->upper_layer_info);
36351256Syl150051 		/*
36363115Syl150051 		 * This feature implements adaptive receive interrupt
36371256Syl150051 		 * coalecing. It is disabled by default. To enable it
36381256Syl150051 		 * set hldev->config.rxufca_lo_lim to be not equal to
36391256Syl150051 		 * hldev->config.rxufca_hi_lim.
36401256Syl150051 		 *
36411256Syl150051 		 * We are using HW timer for this feature, so
36421256Syl150051 		 * use needs to configure hldev->config.rxufca_lbolt_period
36431256Syl150051 		 * which is essentially a time slice of timer.
36441256Syl150051 		 *
36451256Syl150051 		 * For those who familiar with Linux, lbolt means jiffies
36461256Syl150051 		 * of this timer. I.e. timer tick.
36471256Syl150051 		 */
36483115Syl150051 		if (hldev->config.rxufca_lo_lim !=
36493115Syl150051 				hldev->config.rxufca_hi_lim &&
36503115Syl150051 		    hldev->config.rxufca_lo_lim != 0) {
36513115Syl150051 			for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) {
36523115Syl150051 				if (!hldev->config.ring.queue[i].configured)
36533115Syl150051 					continue;
36543115Syl150051 				if (hldev->config.ring.queue[i].rti.urange_a)
36551256Syl150051 					__hal_update_rxufca(hldev, i);
36561256Syl150051 			}
36571256Syl150051 		}
36583115Syl150051 
36593115Syl150051 		/*
36603115Syl150051 		 * This feature implements adaptive TTI timer re-calculation
36613115Syl150051 		 * based on host utilization, number of interrupt processed,
36623115Syl150051 		 * number of RXD per tick and avarage length of packets per
36633115Syl150051 		 * tick.
36643115Syl150051 		 */
36653115Syl150051 		if (hldev->config.bimodal_interrupts) {
36663115Syl150051 			for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) {
36673115Syl150051 				if (!hldev->config.ring.queue[i].configured)
36683115Syl150051 					continue;
36693115Syl150051 				if (hldev->bimodal_tti[i].enabled)
36703115Syl150051 					__hal_update_bimodal(hldev, i);
36713115Syl150051 			}
36723115Syl150051 		}
36731256Syl150051 	}
36741256Syl150051 
36751256Syl150051 	return XGE_HAL_OK;
36761256Syl150051 }
36771256Syl150051 
36781256Syl150051 /*
36791256Syl150051  * __hal_device_handle_txdma - Handle TxDMA interrupt reason
36801256Syl150051  * @hldev: HAL device handle.
36811256Syl150051  * @reason: interrupt reason
36821256Syl150051  */
36831256Syl150051 xge_hal_status_e
__hal_device_handle_txdma(xge_hal_device_t * hldev,u64 reason)36841256Syl150051 __hal_device_handle_txdma(xge_hal_device_t *hldev, u64 reason)
36851256Syl150051 {
36861256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
36871256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
36886937Sxw161283 	u64 val64, temp64, err;
36891256Syl150051 
36901256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
36911256Syl150051 				&isrbar0->txdma_int_status);
36921256Syl150051 	if (val64 & XGE_HAL_TXDMA_PFC_INT) {
36931256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
36941256Syl150051 				&isrbar0->pfc_err_reg);
36951256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
36961256Syl150051 				err, &isrbar0->pfc_err_reg);
36976937Sxw161283 		hldev->stats.sw_dev_info_stats.pfc_err_cnt++;
36986937Sxw161283 		temp64 = XGE_HAL_PFC_ECC_DB_ERR|XGE_HAL_PFC_SM_ERR_ALARM
36996937Sxw161283 			|XGE_HAL_PFC_MISC_0_ERR|XGE_HAL_PFC_MISC_1_ERR
37006937Sxw161283 			|XGE_HAL_PFC_PCIX_ERR;
37016937Sxw161283 		if (val64 & temp64)
37026937Sxw161283 			goto reset;
37031256Syl150051 	}
37041256Syl150051 	if (val64 & XGE_HAL_TXDMA_TDA_INT) {
37051256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37061256Syl150051 				&isrbar0->tda_err_reg);
37071256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37081256Syl150051 				err, &isrbar0->tda_err_reg);
37096937Sxw161283 		hldev->stats.sw_dev_info_stats.tda_err_cnt++;
37106937Sxw161283 		temp64 = XGE_HAL_TDA_Fn_ECC_DB_ERR|XGE_HAL_TDA_SM0_ERR_ALARM
37116937Sxw161283 			|XGE_HAL_TDA_SM1_ERR_ALARM;
37126937Sxw161283 		if (val64 & temp64)
37136937Sxw161283 			goto reset;
37141256Syl150051 	}
37151256Syl150051 	if (val64 & XGE_HAL_TXDMA_PCC_INT) {
37161256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37171256Syl150051 				&isrbar0->pcc_err_reg);
37181256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37191256Syl150051 				err, &isrbar0->pcc_err_reg);
37206937Sxw161283 		hldev->stats.sw_dev_info_stats.pcc_err_cnt++;
37216937Sxw161283 		temp64 = XGE_HAL_PCC_FB_ECC_DB_ERR|XGE_HAL_PCC_TXB_ECC_DB_ERR
37226937Sxw161283 			|XGE_HAL_PCC_SM_ERR_ALARM|XGE_HAL_PCC_WR_ERR_ALARM
37236937Sxw161283 			|XGE_HAL_PCC_N_SERR|XGE_HAL_PCC_6_COF_OV_ERR
37246937Sxw161283 			|XGE_HAL_PCC_7_COF_OV_ERR|XGE_HAL_PCC_6_LSO_OV_ERR
37256937Sxw161283 			|XGE_HAL_PCC_7_LSO_OV_ERR;
37266937Sxw161283 		if (val64 & temp64)
37276937Sxw161283 			goto reset;
37281256Syl150051 	}
37291256Syl150051 	if (val64 & XGE_HAL_TXDMA_TTI_INT) {
37301256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37311256Syl150051 				&isrbar0->tti_err_reg);
37321256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37331256Syl150051 				err, &isrbar0->tti_err_reg);
37346937Sxw161283 		hldev->stats.sw_dev_info_stats.tti_err_cnt++;
37356937Sxw161283 		temp64 = XGE_HAL_TTI_SM_ERR_ALARM;
37366937Sxw161283 		if (val64 & temp64)
37376937Sxw161283 			goto reset;
37381256Syl150051 	}
37391256Syl150051 	if (val64 & XGE_HAL_TXDMA_LSO_INT) {
37401256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37411256Syl150051 				&isrbar0->lso_err_reg);
37421256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37431256Syl150051 				err, &isrbar0->lso_err_reg);
37446937Sxw161283 		hldev->stats.sw_dev_info_stats.lso_err_cnt++;
37456937Sxw161283 		temp64 = XGE_HAL_LSO6_ABORT|XGE_HAL_LSO7_ABORT
37466937Sxw161283 			|XGE_HAL_LSO6_SM_ERR_ALARM|XGE_HAL_LSO7_SM_ERR_ALARM;
37476937Sxw161283 		if (val64 & temp64)
37486937Sxw161283 			goto reset;
37491256Syl150051 	}
37501256Syl150051 	if (val64 & XGE_HAL_TXDMA_TPA_INT) {
37511256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37521256Syl150051 				&isrbar0->tpa_err_reg);
37531256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37541256Syl150051 				err, &isrbar0->tpa_err_reg);
37556937Sxw161283 		hldev->stats.sw_dev_info_stats.tpa_err_cnt++;
37566937Sxw161283 		temp64 = XGE_HAL_TPA_SM_ERR_ALARM;
37576937Sxw161283 		if (val64 & temp64)
37586937Sxw161283 			goto reset;
37591256Syl150051 	}
37601256Syl150051 	if (val64 & XGE_HAL_TXDMA_SM_INT) {
37611256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37621256Syl150051 				&isrbar0->sm_err_reg);
37631256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37641256Syl150051 				err, &isrbar0->sm_err_reg);
37656937Sxw161283 		hldev->stats.sw_dev_info_stats.sm_err_cnt++;
37666937Sxw161283 		temp64 = XGE_HAL_SM_SM_ERR_ALARM;
37676937Sxw161283 		if (val64 & temp64)
37686937Sxw161283 			goto reset;
37696937Sxw161283 	}
37706937Sxw161283 
37716937Sxw161283 	return XGE_HAL_OK;
37726937Sxw161283 
37736937Sxw161283 reset : (void) xge_hal_device_reset(hldev);
37746937Sxw161283 	(void) xge_hal_device_enable(hldev);
37756937Sxw161283 	xge_hal_device_intr_enable(hldev);
37761256Syl150051 	return XGE_HAL_OK;
37771256Syl150051 }
37781256Syl150051 
37791256Syl150051 /*
37801256Syl150051  * __hal_device_handle_txmac - Handle TxMAC interrupt reason
37811256Syl150051  * @hldev: HAL device handle.
37821256Syl150051  * @reason: interrupt reason
37831256Syl150051  */
37841256Syl150051 xge_hal_status_e
__hal_device_handle_txmac(xge_hal_device_t * hldev,u64 reason)37851256Syl150051 __hal_device_handle_txmac(xge_hal_device_t *hldev, u64 reason)
37861256Syl150051 {
37871256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
37881256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
37896937Sxw161283 	u64 val64, temp64;
37901256Syl150051 
37911256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37921256Syl150051 				&isrbar0->mac_int_status);
37931256Syl150051 	if (!(val64 & XGE_HAL_MAC_INT_STATUS_TMAC_INT))
37941256Syl150051 		return XGE_HAL_OK;
37951256Syl150051 
37961256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
37971256Syl150051 				&isrbar0->mac_tmac_err_reg);
37981256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
37991256Syl150051 				val64, &isrbar0->mac_tmac_err_reg);
38006937Sxw161283 	hldev->stats.sw_dev_info_stats.mac_tmac_err_cnt++;
38016937Sxw161283 	temp64 = XGE_HAL_TMAC_TX_BUF_OVRN|XGE_HAL_TMAC_TX_SM_ERR;
38026937Sxw161283 	if (val64 & temp64) {
38036937Sxw161283 		(void) xge_hal_device_reset(hldev);
38046937Sxw161283 		(void) xge_hal_device_enable(hldev);
38056937Sxw161283 		xge_hal_device_intr_enable(hldev);
38066937Sxw161283 	}
38071256Syl150051 
38081256Syl150051 	return XGE_HAL_OK;
38091256Syl150051 }
38101256Syl150051 
38111256Syl150051 /*
38121256Syl150051  * __hal_device_handle_txxgxs - Handle TxXGXS interrupt reason
38131256Syl150051  * @hldev: HAL device handle.
38141256Syl150051  * @reason: interrupt reason
38151256Syl150051  */
38161256Syl150051 xge_hal_status_e
__hal_device_handle_txxgxs(xge_hal_device_t * hldev,u64 reason)38171256Syl150051 __hal_device_handle_txxgxs(xge_hal_device_t *hldev, u64 reason)
38181256Syl150051 {
38196937Sxw161283 	xge_hal_pci_bar0_t *isrbar0 =
38206937Sxw161283 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
38216937Sxw161283 	u64 val64, temp64;
38226937Sxw161283 
38236937Sxw161283 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
38246937Sxw161283 				&isrbar0->xgxs_int_status);
38256937Sxw161283 	if (!(val64 & XGE_HAL_XGXS_INT_STATUS_TXGXS))
38266937Sxw161283 		return XGE_HAL_OK;
38276937Sxw161283 
38286937Sxw161283 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
38296937Sxw161283 				&isrbar0->xgxs_txgxs_err_reg);
38306937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
38316937Sxw161283 				val64, &isrbar0->xgxs_txgxs_err_reg);
38326937Sxw161283 	hldev->stats.sw_dev_info_stats.xgxs_txgxs_err_cnt++;
38336937Sxw161283 	temp64 = XGE_HAL_TXGXS_ESTORE_UFLOW|XGE_HAL_TXGXS_TX_SM_ERR;
38346937Sxw161283 	if (val64 & temp64) {
38356937Sxw161283 		(void) xge_hal_device_reset(hldev);
38366937Sxw161283 		(void) xge_hal_device_enable(hldev);
38376937Sxw161283 		xge_hal_device_intr_enable(hldev);
38386937Sxw161283 	}
38391256Syl150051 
38401256Syl150051 	return XGE_HAL_OK;
38411256Syl150051 }
38421256Syl150051 
38431256Syl150051 /*
38441256Syl150051  * __hal_device_handle_rxpic - Handle RxPIC interrupt reason
38451256Syl150051  * @hldev: HAL device handle.
38461256Syl150051  * @reason: interrupt reason
38471256Syl150051  */
38481256Syl150051 xge_hal_status_e
__hal_device_handle_rxpic(xge_hal_device_t * hldev,u64 reason)38491256Syl150051 __hal_device_handle_rxpic(xge_hal_device_t *hldev, u64 reason)
38501256Syl150051 {
38511256Syl150051 	/* FIXME: handle register */
38521256Syl150051 
38531256Syl150051 	return XGE_HAL_OK;
38541256Syl150051 }
38551256Syl150051 
38561256Syl150051 /*
38571256Syl150051  * __hal_device_handle_rxdma - Handle RxDMA interrupt reason
38581256Syl150051  * @hldev: HAL device handle.
38591256Syl150051  * @reason: interrupt reason
38601256Syl150051  */
38611256Syl150051 xge_hal_status_e
__hal_device_handle_rxdma(xge_hal_device_t * hldev,u64 reason)38621256Syl150051 __hal_device_handle_rxdma(xge_hal_device_t *hldev, u64 reason)
38631256Syl150051 {
38641256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
38651256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
38666937Sxw161283 	u64 val64, err, temp64;
38671256Syl150051 
38681256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
38691256Syl150051 				&isrbar0->rxdma_int_status);
38701256Syl150051 	if (val64 & XGE_HAL_RXDMA_RC_INT) {
38711256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
38721256Syl150051 				&isrbar0->rc_err_reg);
38731256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
38741256Syl150051 				err, &isrbar0->rc_err_reg);
38756937Sxw161283 		hldev->stats.sw_dev_info_stats.rc_err_cnt++;
38766937Sxw161283 		temp64 = XGE_HAL_RC_PRCn_ECC_DB_ERR|XGE_HAL_RC_FTC_ECC_DB_ERR
38776937Sxw161283 			|XGE_HAL_RC_PRCn_SM_ERR_ALARM
38786937Sxw161283 			|XGE_HAL_RC_FTC_SM_ERR_ALARM;
38796937Sxw161283 		if (val64 & temp64)
38806937Sxw161283 			goto reset;
38811256Syl150051 	}
38821256Syl150051 	if (val64 & XGE_HAL_RXDMA_RPA_INT) {
38831256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
38841256Syl150051 				&isrbar0->rpa_err_reg);
38851256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
38861256Syl150051 				err, &isrbar0->rpa_err_reg);
38876937Sxw161283 		hldev->stats.sw_dev_info_stats.rpa_err_cnt++;
38886937Sxw161283 		temp64 = XGE_HAL_RPA_SM_ERR_ALARM|XGE_HAL_RPA_CREDIT_ERR;
38896937Sxw161283 		if (val64 & temp64)
38906937Sxw161283 			goto reset;
38911256Syl150051 	}
38921256Syl150051 	if (val64 & XGE_HAL_RXDMA_RDA_INT) {
38931256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
38941256Syl150051 				&isrbar0->rda_err_reg);
38951256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
38961256Syl150051 				err, &isrbar0->rda_err_reg);
38976937Sxw161283 		hldev->stats.sw_dev_info_stats.rda_err_cnt++;
38986937Sxw161283 		temp64 = XGE_HAL_RDA_RXDn_ECC_DB_ERR
38996937Sxw161283 			|XGE_HAL_RDA_FRM_ECC_DB_N_AERR
39006937Sxw161283 			|XGE_HAL_RDA_SM1_ERR_ALARM|XGE_HAL_RDA_SM0_ERR_ALARM
39016937Sxw161283 			|XGE_HAL_RDA_RXD_ECC_DB_SERR;
39026937Sxw161283 		if (val64 & temp64)
39036937Sxw161283 			goto reset;
39041256Syl150051 	}
39051256Syl150051 	if (val64 & XGE_HAL_RXDMA_RTI_INT) {
39061256Syl150051 		err = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
39071256Syl150051 				&isrbar0->rti_err_reg);
39081256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
39091256Syl150051 				err, &isrbar0->rti_err_reg);
39106937Sxw161283 		hldev->stats.sw_dev_info_stats.rti_err_cnt++;
39116937Sxw161283 		temp64 = XGE_HAL_RTI_SM_ERR_ALARM;
39126937Sxw161283 		if (val64 & temp64)
39136937Sxw161283 			goto reset;
39146937Sxw161283 	}
39156937Sxw161283 
39166937Sxw161283 	return XGE_HAL_OK;
39176937Sxw161283 
39186937Sxw161283 reset : (void) xge_hal_device_reset(hldev);
39196937Sxw161283 	(void) xge_hal_device_enable(hldev);
39206937Sxw161283 	xge_hal_device_intr_enable(hldev);
39211256Syl150051 	return XGE_HAL_OK;
39221256Syl150051 }
39231256Syl150051 
39241256Syl150051 /*
39251256Syl150051  * __hal_device_handle_rxmac - Handle RxMAC interrupt reason
39261256Syl150051  * @hldev: HAL device handle.
39271256Syl150051  * @reason: interrupt reason
39281256Syl150051  */
39291256Syl150051 xge_hal_status_e
__hal_device_handle_rxmac(xge_hal_device_t * hldev,u64 reason)39301256Syl150051 __hal_device_handle_rxmac(xge_hal_device_t *hldev, u64 reason)
39311256Syl150051 {
39321256Syl150051 	xge_hal_pci_bar0_t *isrbar0 =
39331256Syl150051 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
39346937Sxw161283 	u64 val64, temp64;
39351256Syl150051 
39361256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
39371256Syl150051 				&isrbar0->mac_int_status);
39381256Syl150051 	if (!(val64 & XGE_HAL_MAC_INT_STATUS_RMAC_INT))
39391256Syl150051 		return XGE_HAL_OK;
39401256Syl150051 
39411256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
39421256Syl150051 				&isrbar0->mac_rmac_err_reg);
39431256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
39441256Syl150051 				val64, &isrbar0->mac_rmac_err_reg);
39456937Sxw161283 	hldev->stats.sw_dev_info_stats.mac_rmac_err_cnt++;
39466937Sxw161283 	temp64 = XGE_HAL_RMAC_RX_BUFF_OVRN|XGE_HAL_RMAC_RX_SM_ERR;
39476937Sxw161283 	if (val64 & temp64) {
39486937Sxw161283 		(void) xge_hal_device_reset(hldev);
39496937Sxw161283 		(void) xge_hal_device_enable(hldev);
39506937Sxw161283 		xge_hal_device_intr_enable(hldev);
39516937Sxw161283 	}
39521256Syl150051 
39531256Syl150051 	return XGE_HAL_OK;
39541256Syl150051 }
39551256Syl150051 
39561256Syl150051 /*
39571256Syl150051  * __hal_device_handle_rxxgxs - Handle RxXGXS interrupt reason
39581256Syl150051  * @hldev: HAL device handle.
39591256Syl150051  * @reason: interrupt reason
39601256Syl150051  */
39611256Syl150051 xge_hal_status_e
__hal_device_handle_rxxgxs(xge_hal_device_t * hldev,u64 reason)39621256Syl150051 __hal_device_handle_rxxgxs(xge_hal_device_t *hldev, u64 reason)
39631256Syl150051 {
39646937Sxw161283 	xge_hal_pci_bar0_t *isrbar0 =
39656937Sxw161283 	        (xge_hal_pci_bar0_t *)(void *)hldev->isrbar0;
39666937Sxw161283 	u64 val64, temp64;
39676937Sxw161283 
39686937Sxw161283 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
39696937Sxw161283 				&isrbar0->xgxs_int_status);
39706937Sxw161283 	if (!(val64 & XGE_HAL_XGXS_INT_STATUS_RXGXS))
39716937Sxw161283 		return XGE_HAL_OK;
39726937Sxw161283 
39736937Sxw161283 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
39746937Sxw161283 				&isrbar0->xgxs_rxgxs_err_reg);
39756937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
39766937Sxw161283 				val64, &isrbar0->xgxs_rxgxs_err_reg);
39776937Sxw161283 	hldev->stats.sw_dev_info_stats.xgxs_rxgxs_err_cnt++;
39786937Sxw161283 	temp64 = XGE_HAL_RXGXS_ESTORE_OFLOW|XGE_HAL_RXGXS_RX_SM_ERR;
39796937Sxw161283 	if (val64 & temp64) {
39806937Sxw161283 		(void) xge_hal_device_reset(hldev);
39816937Sxw161283 		(void) xge_hal_device_enable(hldev);
39826937Sxw161283 		xge_hal_device_intr_enable(hldev);
39836937Sxw161283 	}
39841256Syl150051 
39851256Syl150051 	return XGE_HAL_OK;
39861256Syl150051 }
39871256Syl150051 
39881256Syl150051 /**
39891256Syl150051  * xge_hal_device_enable - Enable device.
39901256Syl150051  * @hldev: HAL device handle.
39911256Syl150051  *
39921256Syl150051  * Enable the specified device: bring up the link/interface.
39931256Syl150051  * Returns:  XGE_HAL_OK - success.
39941256Syl150051  * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device
39951256Syl150051  * to a "quiescent" state.
39961256Syl150051  *
39971256Syl150051  * See also: xge_hal_status_e{}.
39981256Syl150051  *
39991256Syl150051  * Usage: See ex_open{}.
40001256Syl150051  */
40011256Syl150051 xge_hal_status_e
xge_hal_device_enable(xge_hal_device_t * hldev)40021256Syl150051 xge_hal_device_enable(xge_hal_device_t *hldev)
40031256Syl150051 {
40041256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
40051256Syl150051 	u64 val64;
40061256Syl150051 	u64 adp_status;
40071256Syl150051 	int i, j;
40081256Syl150051 
40091256Syl150051 	if (!hldev->hw_is_initialized) {
40101256Syl150051 		xge_hal_status_e status;
40111256Syl150051 
40121256Syl150051 		status = __hal_device_hw_initialize(hldev);
40131256Syl150051 		if (status != XGE_HAL_OK) {
40141256Syl150051 			return status;
40151256Syl150051 		}
40161256Syl150051 	}
40171256Syl150051 
40181256Syl150051 	/*
40191256Syl150051 	 * Not needed in most cases, i.e.
40201256Syl150051 	 * when device_disable() is followed by reset -
40211256Syl150051 	 * the latter copies back PCI config space, along with
40221256Syl150051 	 * the bus mastership - see __hal_device_reset().
40231256Syl150051 	 * However, there are/may-in-future be other cases, and
40241256Syl150051 	 * does not hurt.
40251256Syl150051 	 */
40261256Syl150051 	__hal_device_bus_master_enable(hldev);
40271256Syl150051 
40281256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
40291256Syl150051 		/*
40301256Syl150051 		 * Configure the link stability period.
40311256Syl150051 		 */
40321256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
40331256Syl150051 					      &bar0->misc_control);
40341256Syl150051 		if (hldev->config.link_stability_period !=
40351256Syl150051 				XGE_HAL_DEFAULT_USE_HARDCODE) {
40361256Syl150051 
40371256Syl150051 			val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD(
40381256Syl150051 					hldev->config.link_stability_period);
40391256Syl150051 		} else {
40401256Syl150051 			/*
40411256Syl150051 			 * Use the link stability period 1 ms as default
40421256Syl150051 			 */
40431256Syl150051 			val64 |= XGE_HAL_MISC_CONTROL_LINK_STABILITY_PERIOD(
40441256Syl150051 					XGE_HAL_DEFAULT_LINK_STABILITY_PERIOD);
40451256Syl150051 		}
40461256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
40471256Syl150051 				       val64, &bar0->misc_control);
40481256Syl150051 
40491256Syl150051 		/*
40501256Syl150051 		 * Clearing any possible Link up/down interrupts that
40511256Syl150051 		 * could have popped up just before Enabling the card.
40521256Syl150051 		 */
40531256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
40541256Syl150051 					      &bar0->misc_int_reg);
40551256Syl150051 		if (val64) {
40561256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
40571256Syl150051 					       val64, &bar0->misc_int_reg);
40581256Syl150051 			xge_debug_device(XGE_TRACE, "%s","link state cleared");
40591256Syl150051 		}
40601256Syl150051 	} else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) {
40611256Syl150051 		/*
40621256Syl150051 		 * Clearing any possible Link state change interrupts that
40631256Syl150051 		 * could have popped up just before Enabling the card.
40641256Syl150051 		 */
40651256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
40661256Syl150051 			&bar0->mac_rmac_err_reg);
40671256Syl150051 		if (val64) {
40681256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
40691256Syl150051 					       val64, &bar0->mac_rmac_err_reg);
40701256Syl150051 			xge_debug_device(XGE_TRACE, "%s", "link state cleared");
40711256Syl150051 		}
40721256Syl150051 	}
40731256Syl150051 
40741256Syl150051 	if (__hal_device_wait_quiescent(hldev, &val64)) {
40751256Syl150051 		return XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
40761256Syl150051 	}
40771256Syl150051 
40781256Syl150051 	/* Enabling Laser. */
40791256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
40801256Syl150051 				    &bar0->adapter_control);
40811256Syl150051 	val64 |= XGE_HAL_ADAPTER_EOI_TX_ON;
40821256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
40831256Syl150051 	                     &bar0->adapter_control);
40841256Syl150051 
40851256Syl150051 	/* let link establish */
40861256Syl150051 	xge_os_mdelay(1);
40871256Syl150051 
40881256Syl150051 	/* set link down untill poll() routine will set it up (maybe) */
40891256Syl150051 	hldev->link_state = XGE_HAL_LINK_DOWN;
40901256Syl150051 
40911256Syl150051 	/* If link is UP (adpter is connected) then enable the adapter */
40921256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
40931256Syl150051 	                            &bar0->adapter_status);
40941256Syl150051 	if( val64 & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
40951256Syl150051 		     XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT) ) {
40961256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
40971256Syl150051 		                        &bar0->adapter_control);
40981256Syl150051 		val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON);
40991256Syl150051 	} else {
41001256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
41011256Syl150051 		                           &bar0->adapter_control);
41021256Syl150051 		val64 = val64 | ( XGE_HAL_ADAPTER_EOI_TX_ON |
41031256Syl150051 				  XGE_HAL_ADAPTER_LED_ON );
41041256Syl150051 	}
41051256Syl150051 
41061256Syl150051 	val64 = val64 | XGE_HAL_ADAPTER_CNTL_EN;   /* adapter enable */
41071256Syl150051 	val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN); /* ECC enable */
41081256Syl150051 	xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0, val64,
41091256Syl150051 			      &bar0->adapter_control);
41101256Syl150051 
41111256Syl150051 	/* We spin here waiting for the Link to come up.
41121256Syl150051 	 * This is the fix for the Link being unstable after the reset. */
41131256Syl150051 	i = 0;
41141256Syl150051 	j = 0;
41151256Syl150051 	do
41161256Syl150051 	{
41171256Syl150051 		adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
41181256Syl150051 		                                &bar0->adapter_status);
41191256Syl150051 
41201256Syl150051 		/* Read the adapter control register for Adapter_enable bit */
41211256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
41221256Syl150051 		                           &bar0->adapter_control);
41231256Syl150051 		if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
41241256Syl150051 				    XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)) &&
41251256Syl150051 		    (val64 & XGE_HAL_ADAPTER_CNTL_EN)) {
41261256Syl150051 			j++;
41271256Syl150051 			if (j >= hldev->config.link_valid_cnt) {
41281256Syl150051 				if (xge_hal_device_status(hldev, &adp_status) ==
41291256Syl150051 							XGE_HAL_OK) {
41301256Syl150051 					if (__hal_verify_pcc_idle(hldev,
41311256Syl150051 						  adp_status) != XGE_HAL_OK) {
41321256Syl150051 					   return
41331256Syl150051 					    XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
41341256Syl150051 					}
41351256Syl150051 					xge_debug_device(XGE_TRACE,
41363115Syl150051 					      "adp_status: "XGE_OS_LLXFMT
41373115Syl150051 					      ", link is up on "
41381256Syl150051 					      "adapter enable!",
41391256Syl150051 					      (unsigned long long)adp_status);
41401256Syl150051 					val64 = xge_os_pio_mem_read64(
41411256Syl150051 							hldev->pdev,
41421256Syl150051 							hldev->regh0,
41431256Syl150051 							&bar0->adapter_control);
41441256Syl150051 					val64 = val64|
41451256Syl150051 						(XGE_HAL_ADAPTER_EOI_TX_ON |
41461256Syl150051 						 XGE_HAL_ADAPTER_LED_ON );
41471256Syl150051 					xge_os_pio_mem_write64(hldev->pdev,
41481256Syl150051 					                hldev->regh0, val64,
41491256Syl150051 					                &bar0->adapter_control);
41501256Syl150051 					xge_os_mdelay(1);
41511256Syl150051 
41521256Syl150051 					val64 = xge_os_pio_mem_read64(
41531256Syl150051 							hldev->pdev,
41541256Syl150051 							hldev->regh0,
41551256Syl150051 							&bar0->adapter_control);
41561256Syl150051 					break;    /* out of for loop */
41571256Syl150051 				} else {
41581256Syl150051 				       return
41591256Syl150051 					   XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
41601256Syl150051 				}
41611256Syl150051 			}
41621256Syl150051 		} else {
41631256Syl150051 			j = 0;  /* Reset the count */
41641256Syl150051 			/* Turn on the Laser */
41651256Syl150051 			val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
41661256Syl150051 			                &bar0->adapter_control);
41671256Syl150051 			val64 = val64 | XGE_HAL_ADAPTER_EOI_TX_ON;
41681256Syl150051 			xge_os_pio_mem_write64 (hldev->pdev, hldev->regh0,
41691256Syl150051 						val64, &bar0->adapter_control);
41701256Syl150051 
41711256Syl150051 			xge_os_mdelay(1);
41721256Syl150051 
41731256Syl150051 			/* Now re-enable it as due to noise, hardware
41741256Syl150051 			 * turned it off */
41751256Syl150051 			val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
41761256Syl150051 			                            &bar0->adapter_control);
41771256Syl150051 			val64 |= XGE_HAL_ADAPTER_CNTL_EN;
41781256Syl150051 			val64 = val64 & (~XGE_HAL_ADAPTER_ECC_EN);/*ECC enable*/
41791256Syl150051 			xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
41801256Syl150051 			                    &bar0->adapter_control);
41811256Syl150051 		}
41821256Syl150051 		xge_os_mdelay(1); /* Sleep for 1 msec */
41831256Syl150051 		i++;
41841256Syl150051 	} while (i < hldev->config.link_retry_cnt);
41851256Syl150051 
41861256Syl150051 	__hal_device_led_actifity_fix(hldev);
41871256Syl150051 
41881256Syl150051 #ifndef  XGE_HAL_PROCESS_LINK_INT_IN_ISR
41891256Syl150051 	/* Here we are performing soft reset on XGXS to force link down.
41901256Syl150051 	 * Since link is already up, we will get link state change
41911256Syl150051 	 * poll notificatoin after adapter is enabled */
41921256Syl150051 
41936937Sxw161283 	__hal_serial_mem_write64(hldev, 0x80010515001E0000ULL,
41946937Sxw161283 				 &bar0->dtx_control);
41956937Sxw161283 	(void) __hal_serial_mem_read64(hldev, &bar0->dtx_control);
41966937Sxw161283 
41976937Sxw161283 	__hal_serial_mem_write64(hldev, 0x80010515001E00E0ULL,
41986937Sxw161283 				 &bar0->dtx_control);
41996937Sxw161283 	(void) __hal_serial_mem_read64(hldev, &bar0->dtx_control);
42006937Sxw161283 
42016937Sxw161283 	__hal_serial_mem_write64(hldev, 0x80070515001F00E4ULL,
42026937Sxw161283 				 &bar0->dtx_control);
42036937Sxw161283 	(void) __hal_serial_mem_read64(hldev, &bar0->dtx_control);
42041256Syl150051 
42051256Syl150051 	xge_os_mdelay(100); /* Sleep for 500 msec */
42061256Syl150051 #else
42071256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)
42081256Syl150051 #endif
42091256Syl150051 	{
42101256Syl150051 		/*
42111256Syl150051 		 * With some switches the link state change interrupt does not
42121256Syl150051 		 * occur even though the xgxs reset is done as per SPN-006. So,
42131256Syl150051 		 * poll the adapter status register and check if the link state
42141256Syl150051 		 * is ok.
42151256Syl150051 		 */
42161256Syl150051 		adp_status = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
42171256Syl150051 						   &bar0->adapter_status);
42181256Syl150051 		if (!(adp_status & (XGE_HAL_ADAPTER_STATUS_RMAC_REMOTE_FAULT |
42191256Syl150051 		      XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
42201256Syl150051 		{
42211256Syl150051 			xge_debug_device(XGE_TRACE, "%s",
42221256Syl150051 			     "enable device causing link state change ind..");
42231256Syl150051 			(void) __hal_device_handle_link_state_change(hldev);
42241256Syl150051 		}
42251256Syl150051 	}
42261256Syl150051 
42271256Syl150051 	if (hldev->config.stats_refresh_time_sec !=
42281256Syl150051 	    XGE_HAL_STATS_REFRESH_DISABLE)
42291256Syl150051 	        __hal_stats_enable(&hldev->stats);
42301256Syl150051 
42311256Syl150051 	return XGE_HAL_OK;
42321256Syl150051 }
42331256Syl150051 
42341256Syl150051 /**
42351256Syl150051  * xge_hal_device_disable - Disable Xframe adapter.
42361256Syl150051  * @hldev: Device handle.
42371256Syl150051  *
42381256Syl150051  * Disable this device. To gracefully reset the adapter, the host should:
42391256Syl150051  *
42401256Syl150051  *	- call xge_hal_device_disable();
42411256Syl150051  *
42421256Syl150051  *	- call xge_hal_device_intr_disable();
42431256Syl150051  *
42441256Syl150051  *	- close all opened channels and clean up outstanding resources;
42451256Syl150051  *
42461256Syl150051  *	- do some work (error recovery, change mtu, reset, etc);
42471256Syl150051  *
42481256Syl150051  *	- call xge_hal_device_enable();
42491256Syl150051  *
42501256Syl150051  *	- open channels, replenish RxDs, etc.
42511256Syl150051  *
42521256Syl150051  *	- call xge_hal_device_intr_enable().
42531256Syl150051  *
42541256Syl150051  * Note: Disabling the device does _not_ include disabling of interrupts.
42551256Syl150051  * After disabling the device stops receiving new frames but those frames
42561256Syl150051  * that were already in the pipe will keep coming for some few milliseconds.
42571256Syl150051  *
42581256Syl150051  * Returns:  XGE_HAL_OK - success.
42591256Syl150051  * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to
42601256Syl150051  * a "quiescent" state.
42611256Syl150051  *
42621256Syl150051  * See also: xge_hal_status_e{}.
42631256Syl150051  */
42641256Syl150051 xge_hal_status_e
xge_hal_device_disable(xge_hal_device_t * hldev)42651256Syl150051 xge_hal_device_disable(xge_hal_device_t *hldev)
42661256Syl150051 {
42671256Syl150051 	xge_hal_status_e status = XGE_HAL_OK;
42681256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
42691256Syl150051 	u64 val64;
42701256Syl150051 
42711256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "turn off laser, cleanup hardware");
42721256Syl150051 
42731256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
42741256Syl150051 	                            &bar0->adapter_control);
42751256Syl150051 	val64 = val64 & (~XGE_HAL_ADAPTER_CNTL_EN);
42761256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
42771256Syl150051 	                     &bar0->adapter_control);
42781256Syl150051 
42791256Syl150051 	if (__hal_device_wait_quiescent(hldev, &val64) != XGE_HAL_OK) {
42801256Syl150051 		status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
42811256Syl150051 	}
42821256Syl150051 
42831256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->adapter_status, 1,
42841256Syl150051 		 XGE_HAL_ADAPTER_STATUS_RC_PRC_QUIESCENT,
42851256Syl150051 		 XGE_HAL_DEVICE_QUIESCENT_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
42861256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "PRC is not QUIESCENT!");
42871256Syl150051 		status = XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT;
42881256Syl150051 	}
42891256Syl150051 
42901256Syl150051 	if (hldev->config.stats_refresh_time_sec !=
42911256Syl150051 	    XGE_HAL_STATS_REFRESH_DISABLE)
42921256Syl150051                 __hal_stats_disable(&hldev->stats);
42931256Syl150051 #ifdef XGE_DEBUG_ASSERT
42941256Syl150051         else
42951256Syl150051 	        xge_assert(!hldev->stats.is_enabled);
42961256Syl150051 #endif
42971256Syl150051 
42983115Syl150051 #ifndef XGE_HAL_DONT_DISABLE_BUS_MASTER_ON_STOP
42991256Syl150051 	__hal_device_bus_master_disable(hldev);
43003115Syl150051 #endif
43011256Syl150051 
43021256Syl150051 	return status;
43031256Syl150051 }
43041256Syl150051 
43051256Syl150051 /**
43061256Syl150051  * xge_hal_device_reset - Reset device.
43071256Syl150051  * @hldev: HAL device handle.
43081256Syl150051  *
43091256Syl150051  * Soft-reset the device, reset the device stats except reset_cnt.
43101256Syl150051  *
43111256Syl150051  * After reset is done, will try to re-initialize HW.
43121256Syl150051  *
43131256Syl150051  * Returns:  XGE_HAL_OK - success.
43141256Syl150051  * XGE_HAL_ERR_DEVICE_NOT_INITIALIZED - Device is not initialized.
43151256Syl150051  * XGE_HAL_ERR_RESET_FAILED - Reset failed.
43161256Syl150051  *
43171256Syl150051  * See also: xge_hal_status_e{}.
43181256Syl150051  */
43191256Syl150051 xge_hal_status_e
xge_hal_device_reset(xge_hal_device_t * hldev)43201256Syl150051 xge_hal_device_reset(xge_hal_device_t *hldev)
43211256Syl150051 {
43221256Syl150051 	xge_hal_status_e status;
43231256Syl150051 
43241256Syl150051 	/* increment the soft reset counter */
43251256Syl150051 	u32 reset_cnt = hldev->stats.sw_dev_info_stats.soft_reset_cnt;
43261256Syl150051 
43273115Syl150051 	xge_debug_device(XGE_TRACE, "%s (%d)", "resetting the device", reset_cnt);
43281256Syl150051 
43291256Syl150051 	if (!hldev->is_initialized)
43301256Syl150051 		return XGE_HAL_ERR_DEVICE_NOT_INITIALIZED;
43311256Syl150051 
43321256Syl150051 	/* actual "soft" reset of the adapter */
43331256Syl150051 	status = __hal_device_reset(hldev);
43341256Syl150051 
43351256Syl150051 	/* reset all stats including saved */
43361256Syl150051 	__hal_stats_soft_reset(hldev, 1);
43371256Syl150051 
43381256Syl150051 	/* increment reset counter */
43391256Syl150051 	hldev->stats.sw_dev_info_stats.soft_reset_cnt = reset_cnt + 1;
43401256Syl150051 
43411256Syl150051 	/* re-initialize rxufca_intr_thres */
43421256Syl150051 	hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres;
43431256Syl150051 
43441256Syl150051         hldev->reset_needed_after_close = 0;
43451256Syl150051 
43461256Syl150051 	return status;
43471256Syl150051 }
43481256Syl150051 
43491256Syl150051 /**
43501256Syl150051  * xge_hal_device_status - Check whether Xframe hardware is ready for
43511256Syl150051  * operation.
43521256Syl150051  * @hldev: HAL device handle.
43531256Syl150051  * @hw_status: Xframe status register. Returned by HAL.
43541256Syl150051  *
43551256Syl150051  * Check whether Xframe hardware is ready for operation.
43561256Syl150051  * The checking includes TDMA, RDMA, PFC, PIC, MC_DRAM, and the rest
43571256Syl150051  * hardware functional blocks.
43581256Syl150051  *
43591256Syl150051  * Returns: XGE_HAL_OK if the device is ready for operation. Otherwise
43601256Syl150051  * returns XGE_HAL_FAIL. Also, fills in  adapter status (in @hw_status).
43611256Syl150051  *
43621256Syl150051  * See also: xge_hal_status_e{}.
43631256Syl150051  * Usage: See ex_open{}.
43641256Syl150051  */
43651256Syl150051 xge_hal_status_e
xge_hal_device_status(xge_hal_device_t * hldev,u64 * hw_status)43661256Syl150051 xge_hal_device_status(xge_hal_device_t *hldev, u64 *hw_status)
43671256Syl150051 {
43681256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
43691256Syl150051 	u64 tmp64;
43701256Syl150051 
43711256Syl150051 	tmp64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
43721256Syl150051 	                            &bar0->adapter_status);
43731256Syl150051 
43746937Sxw161283 	*hw_status = tmp64;
43751256Syl150051 
43761256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TDMA_READY)) {
43771256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "TDMA is not ready!");
43781256Syl150051 		return XGE_HAL_FAIL;
43791256Syl150051 	}
43801256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_RDMA_READY)) {
43811256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "RDMA is not ready!");
43821256Syl150051 		return XGE_HAL_FAIL;
43831256Syl150051 	}
43841256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PFC_READY)) {
43851256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "PFC is not ready!");
43861256Syl150051 		return XGE_HAL_FAIL;
43871256Syl150051 	}
43881256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_TMAC_BUF_EMPTY)) {
43891256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "TMAC BUF is not empty!");
43901256Syl150051 		return XGE_HAL_FAIL;
43911256Syl150051 	}
43921256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_PIC_QUIESCENT)) {
43931256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "PIC is not QUIESCENT!");
43941256Syl150051 		return XGE_HAL_FAIL;
43951256Syl150051 	}
43961256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_DRAM_READY)) {
43971256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "MC_DRAM is not ready!");
43981256Syl150051 		return XGE_HAL_FAIL;
43991256Syl150051 	}
44001256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_MC_QUEUES_READY)) {
44011256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "MC_QUEUES is not ready!");
44021256Syl150051 		return XGE_HAL_FAIL;
44031256Syl150051 	}
44041256Syl150051 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_M_PLL_LOCK)) {
44051256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "M_PLL is not locked!");
44061256Syl150051 		return XGE_HAL_FAIL;
44071256Syl150051 	}
44086937Sxw161283 #ifndef XGE_HAL_HERC_EMULATION
44096937Sxw161283 	/*
44106937Sxw161283 	 * Andrew: in PCI 33 mode, the P_PLL is not used, and therefore,
44116937Sxw161283 	 * the the P_PLL_LOCK bit in the adapter_status register will
44126937Sxw161283 	 * not be asserted.
44136937Sxw161283 	 */
44146937Sxw161283 	if (!(tmp64 & XGE_HAL_ADAPTER_STATUS_P_PLL_LOCK) &&
44156937Sxw161283 	     xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC &&
44166937Sxw161283 	     hldev->pci_mode != XGE_HAL_PCI_33MHZ_MODE) {
44171256Syl150051 		xge_debug_device(XGE_TRACE, "%s", "P_PLL is not locked!");
44181256Syl150051 		return XGE_HAL_FAIL;
44191256Syl150051 	}
44206937Sxw161283 #endif
44211256Syl150051 
44221256Syl150051 	return XGE_HAL_OK;
44231256Syl150051 }
44241256Syl150051 
44256937Sxw161283 void
__hal_device_msi_intr_endis(xge_hal_device_t * hldev,int flag)44266937Sxw161283 __hal_device_msi_intr_endis(xge_hal_device_t *hldev, int flag)
44276937Sxw161283 {
44286937Sxw161283 	u16 msi_control_reg;
44296937Sxw161283 
44306937Sxw161283 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
44316937Sxw161283 	     xge_offsetof(xge_hal_pci_config_le_t,
44326937Sxw161283 			  msi_control), &msi_control_reg);
44336937Sxw161283 
44346937Sxw161283 	if (flag)
44356937Sxw161283 		msi_control_reg |= 0x1;
44366937Sxw161283 	else
44376937Sxw161283 		msi_control_reg &= ~0x1;
44386937Sxw161283 
44396937Sxw161283 	xge_os_pci_write16(hldev->pdev, hldev->cfgh,
44406937Sxw161283 	     xge_offsetof(xge_hal_pci_config_le_t,
44416937Sxw161283 			     msi_control), msi_control_reg);
44426937Sxw161283 }
44436937Sxw161283 
44446937Sxw161283 void
__hal_device_msix_intr_endis(xge_hal_device_t * hldev,xge_hal_channel_t * channel,int flag)44456937Sxw161283 __hal_device_msix_intr_endis(xge_hal_device_t *hldev,
44466937Sxw161283 			      xge_hal_channel_t *channel, int flag)
44476937Sxw161283 {
44486937Sxw161283 	u64 val64;
44496937Sxw161283 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
44506937Sxw161283 
44516937Sxw161283 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
44526937Sxw161283 		&bar0->xmsi_mask_reg);
44536937Sxw161283 
44546937Sxw161283 	if (flag)
44556937Sxw161283 		val64 &= ~(1LL << ( 63 - channel->msix_idx ));
44566937Sxw161283 	else
44576937Sxw161283 		val64 |= (1LL << ( 63 - channel->msix_idx ));
44586937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
44596937Sxw161283 		&bar0->xmsi_mask_reg);
44606937Sxw161283 }
44611256Syl150051 
44621256Syl150051 /**
44631256Syl150051  * xge_hal_device_intr_enable - Enable Xframe interrupts.
44641256Syl150051  * @hldev: HAL device handle.
44651256Syl150051  * @op: One of the xge_hal_device_intr_e enumerated values specifying
44661256Syl150051  *      the type(s) of interrupts to enable.
44671256Syl150051  *
44681256Syl150051  * Enable Xframe interrupts. The function is to be executed the last in
44691256Syl150051  * Xframe initialization sequence.
44701256Syl150051  *
44711256Syl150051  * See also: xge_hal_device_intr_disable()
44721256Syl150051  */
44731256Syl150051 void
xge_hal_device_intr_enable(xge_hal_device_t * hldev)44741256Syl150051 xge_hal_device_intr_enable(xge_hal_device_t *hldev)
44751256Syl150051 {
44761256Syl150051 	xge_list_t *item;
44771256Syl150051 	u64 val64;
44781256Syl150051 
44791256Syl150051 	/* PRC initialization and configuration */
44801256Syl150051 	xge_list_for_each(item, &hldev->ring_channels) {
44811256Syl150051 		xge_hal_channel_h channel;
44821256Syl150051 		channel = xge_container_of(item, xge_hal_channel_t, item);
44831256Syl150051 		__hal_ring_prc_enable(channel);
44841256Syl150051 	}
44851256Syl150051 
44861256Syl150051 	/* enable traffic only interrupts */
44873115Syl150051 	if (hldev->config.intr_mode != XGE_HAL_INTR_MODE_IRQLINE) {
44883115Syl150051 		/*
44893115Syl150051 		 * make sure all interrupts going to be disabled if MSI
44903115Syl150051 		 * is enabled.
44913115Syl150051 		 */
44926937Sxw161283 #ifdef XGE_HAL_PROCESS_LINK_INT_IN_ISR
44936937Sxw161283 		__hal_device_intr_mgmt(hldev, XGE_HAL_TX_PIC_INTR, 1);
44946937Sxw161283 #else
44953115Syl150051 		__hal_device_intr_mgmt(hldev, XGE_HAL_ALL_INTRS, 0);
44966937Sxw161283 #endif
44973115Syl150051 	} else {
44983115Syl150051 		/*
44993115Syl150051 		 * Enable the Tx traffic interrupts only if the TTI feature is
45003115Syl150051 		 * enabled.
45013115Syl150051 		 */
45023115Syl150051 		val64 = 0;
45033115Syl150051 		if (hldev->tti_enabled)
45043115Syl150051 			val64 = XGE_HAL_TX_TRAFFIC_INTR;
45053115Syl150051 
45063115Syl150051 		if (!hldev->config.bimodal_interrupts)
45073115Syl150051 			val64 |= XGE_HAL_RX_TRAFFIC_INTR;
45083115Syl150051 
45093115Syl150051 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)
45103115Syl150051 			val64 |= XGE_HAL_RX_TRAFFIC_INTR;
45113115Syl150051 
45123115Syl150051 		val64 |=XGE_HAL_TX_PIC_INTR |
45133115Syl150051 			XGE_HAL_MC_INTR |
45146937Sxw161283 			XGE_HAL_TX_DMA_INTR |
45153115Syl150051 			(hldev->config.sched_timer_us !=
45163115Syl150051 			 XGE_HAL_SCHED_TIMER_DISABLED ? XGE_HAL_SCHED_INTR : 0);
45173115Syl150051 		__hal_device_intr_mgmt(hldev, val64, 1);
45183115Syl150051 	}
45196937Sxw161283 
45206937Sxw161283 	/*
45216937Sxw161283 	 * Enable MSI-X interrupts
45226937Sxw161283 	 */
45236937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) {
45246937Sxw161283 
45256937Sxw161283 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
45266937Sxw161283 			/*
45276937Sxw161283 			 * To enable MSI-X, MSI also needs to be enabled,
45286937Sxw161283 			 * due to a bug in the herc NIC.
45296937Sxw161283 			 */
45306937Sxw161283 			__hal_device_msi_intr_endis(hldev, 1);
45316937Sxw161283 		}
45326937Sxw161283 
45336937Sxw161283 
45346937Sxw161283 		/* Enable the MSI-X interrupt for each configured channel */
45356937Sxw161283 		xge_list_for_each(item, &hldev->fifo_channels) {
45366937Sxw161283 			xge_hal_channel_t *channel;
45376937Sxw161283 
45386937Sxw161283 			channel = xge_container_of(item,
45396937Sxw161283 					   xge_hal_channel_t, item);
45406937Sxw161283 
45416937Sxw161283 			/* 0 vector is reserved for alarms */
45426937Sxw161283 			if (!channel->msix_idx)
45436937Sxw161283 				continue;
45446937Sxw161283 
45456937Sxw161283 			__hal_device_msix_intr_endis(hldev, channel, 1);
45466937Sxw161283 		}
45476937Sxw161283 
45486937Sxw161283 		xge_list_for_each(item, &hldev->ring_channels) {
45496937Sxw161283 			xge_hal_channel_t *channel;
45506937Sxw161283 
45516937Sxw161283 			channel = xge_container_of(item,
45526937Sxw161283 					   xge_hal_channel_t, item);
45536937Sxw161283 
45546937Sxw161283 			/* 0 vector is reserved for alarms */
45556937Sxw161283 			if (!channel->msix_idx)
45566937Sxw161283 				continue;
45576937Sxw161283 
45586937Sxw161283 			__hal_device_msix_intr_endis(hldev, channel, 1);
45596937Sxw161283 		}
45606937Sxw161283 	}
45616937Sxw161283 
45621256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "interrupts are enabled");
45631256Syl150051 }
45641256Syl150051 
45651256Syl150051 
45661256Syl150051 /**
45671256Syl150051  * xge_hal_device_intr_disable - Disable Xframe interrupts.
45681256Syl150051  * @hldev: HAL device handle.
45691256Syl150051  * @op: One of the xge_hal_device_intr_e enumerated values specifying
45701256Syl150051  *      the type(s) of interrupts to disable.
45711256Syl150051  *
45721256Syl150051  * Disable Xframe interrupts.
45731256Syl150051  *
45741256Syl150051  * See also: xge_hal_device_intr_enable()
45751256Syl150051  */
45761256Syl150051 void
xge_hal_device_intr_disable(xge_hal_device_t * hldev)45771256Syl150051 xge_hal_device_intr_disable(xge_hal_device_t *hldev)
45781256Syl150051 {
45791256Syl150051 	xge_list_t *item;
45806937Sxw161283 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
45811256Syl150051 	u64 val64;
45821256Syl150051 
45836937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX) {
45846937Sxw161283 
45856937Sxw161283 		if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
45866937Sxw161283 			/*
45876937Sxw161283 			 * To disable MSI-X, MSI also needs to be disabled,
45886937Sxw161283 			 * due to a bug in the herc NIC.
45896937Sxw161283 			 */
45906937Sxw161283 			__hal_device_msi_intr_endis(hldev, 0);
45916937Sxw161283 		}
45926937Sxw161283 
45936937Sxw161283 		/* Disable the MSI-X interrupt for each configured channel */
45946937Sxw161283 		xge_list_for_each(item, &hldev->fifo_channels) {
45956937Sxw161283 			xge_hal_channel_t *channel;
45966937Sxw161283 
45976937Sxw161283 			channel = xge_container_of(item,
45986937Sxw161283 					   xge_hal_channel_t, item);
45996937Sxw161283 
46006937Sxw161283 			/* 0 vector is reserved for alarms */
46016937Sxw161283 			if (!channel->msix_idx)
46026937Sxw161283 				continue;
46036937Sxw161283 
46046937Sxw161283 			__hal_device_msix_intr_endis(hldev, channel, 0);
46056937Sxw161283 
46066937Sxw161283 		}
46076937Sxw161283 
46086937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev,
46096937Sxw161283 			hldev->regh0, 0xFFFFFFFFFFFFFFFFULL,
46106937Sxw161283 			&bar0->tx_traffic_mask);
46116937Sxw161283 
46126937Sxw161283 		xge_list_for_each(item, &hldev->ring_channels) {
46136937Sxw161283 			xge_hal_channel_t *channel;
46146937Sxw161283 
46156937Sxw161283 			channel = xge_container_of(item,
46166937Sxw161283 					   xge_hal_channel_t, item);
46176937Sxw161283 
46186937Sxw161283 			/* 0 vector is reserved for alarms */
46196937Sxw161283 			if (!channel->msix_idx)
46206937Sxw161283 				continue;
46216937Sxw161283 
46226937Sxw161283 			__hal_device_msix_intr_endis(hldev, channel, 0);
46236937Sxw161283 		}
46246937Sxw161283 
46256937Sxw161283 		xge_os_pio_mem_write64(hldev->pdev,
46266937Sxw161283 			hldev->regh0, 0xFFFFFFFFFFFFFFFFULL,
46276937Sxw161283 			&bar0->rx_traffic_mask);
46286937Sxw161283 	}
46296937Sxw161283 
46301256Syl150051 	/*
46311256Syl150051 	 * Disable traffic only interrupts.
46321256Syl150051 	 * Tx traffic interrupts are used only if the TTI feature is
46331256Syl150051 	 * enabled.
46341256Syl150051 	 */
46351256Syl150051 	val64 = 0;
46363115Syl150051 	if (hldev->tti_enabled)
46371256Syl150051 		val64 = XGE_HAL_TX_TRAFFIC_INTR;
46381256Syl150051 
46391256Syl150051 	val64 |= XGE_HAL_RX_TRAFFIC_INTR |
46401256Syl150051 		 XGE_HAL_TX_PIC_INTR |
46411256Syl150051 		 XGE_HAL_MC_INTR |
46421256Syl150051 		 (hldev->config.sched_timer_us != XGE_HAL_SCHED_TIMER_DISABLED ?
46431256Syl150051 						XGE_HAL_SCHED_INTR : 0);
46441256Syl150051 	__hal_device_intr_mgmt(hldev, val64, 0);
46451256Syl150051 
46461256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
46471256Syl150051 	                     0xFFFFFFFFFFFFFFFFULL,
46481256Syl150051 			     &bar0->general_int_mask);
46491256Syl150051 
46501256Syl150051 
46511256Syl150051 	/* disable all configured PRCs */
46521256Syl150051 	xge_list_for_each(item, &hldev->ring_channels) {
46531256Syl150051 		xge_hal_channel_h channel;
46541256Syl150051 		channel = xge_container_of(item, xge_hal_channel_t, item);
46551256Syl150051 		__hal_ring_prc_disable(channel);
46561256Syl150051 	}
46571256Syl150051 
46581256Syl150051 	xge_debug_device(XGE_TRACE, "%s", "interrupts are disabled");
46591256Syl150051 }
46601256Syl150051 
46611256Syl150051 
46621256Syl150051 /**
46631256Syl150051  * xge_hal_device_mcast_enable - Enable Xframe multicast addresses.
46641256Syl150051  * @hldev: HAL device handle.
46651256Syl150051  *
46661256Syl150051  * Enable Xframe multicast addresses.
46671256Syl150051  * Returns: XGE_HAL_OK on success.
46681256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to enable mcast
46691256Syl150051  * feature within the time(timeout).
46701256Syl150051  *
46711256Syl150051  * See also: xge_hal_device_mcast_disable(), xge_hal_status_e{}.
46721256Syl150051  */
46731256Syl150051 xge_hal_status_e
xge_hal_device_mcast_enable(xge_hal_device_t * hldev)46741256Syl150051 xge_hal_device_mcast_enable(xge_hal_device_t *hldev)
46751256Syl150051 {
46761256Syl150051 	u64 val64;
46771256Syl150051 	xge_hal_pci_bar0_t *bar0;
46783115Syl150051 	int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET;
46791256Syl150051 
46801256Syl150051 	if (hldev == NULL)
46811256Syl150051 		return XGE_HAL_ERR_INVALID_DEVICE;
46821256Syl150051 
46831256Syl150051 	if (hldev->mcast_refcnt)
46841256Syl150051 		return XGE_HAL_OK;
46851256Syl150051 
46863115Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
46873115Syl150051 		mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC;
46883115Syl150051 
46891256Syl150051 	hldev->mcast_refcnt = 1;
46901256Syl150051 
46911256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
46921256Syl150051 
46931256Syl150051 	/*  Enable all Multicast addresses */
46941256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
46951256Syl150051 	      XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0x010203040506ULL),
46961256Syl150051 	      &bar0->rmac_addr_data0_mem);
46971256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
46981256Syl150051 	      XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0xfeffffffffffULL),
46991256Syl150051 	      &bar0->rmac_addr_data1_mem);
47001256Syl150051 	val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE |
47011256Syl150051 		XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
47023115Syl150051 		XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset);
47031256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
47041256Syl150051 		            &bar0->rmac_addr_cmd_mem);
47051256Syl150051 
47061256Syl150051 	if (__hal_device_register_poll(hldev,
47071256Syl150051 		&bar0->rmac_addr_cmd_mem, 0,
47081256Syl150051 		XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
47091256Syl150051 		XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
47101256Syl150051 		/* upper layer may require to repeat */
47111256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
47121256Syl150051 	}
47131256Syl150051 
47141256Syl150051 	return XGE_HAL_OK;
47151256Syl150051 }
47161256Syl150051 
47171256Syl150051 /**
47181256Syl150051  * xge_hal_device_mcast_disable - Disable Xframe multicast addresses.
47191256Syl150051  * @hldev: HAL device handle.
47201256Syl150051  *
47211256Syl150051  * Disable Xframe multicast addresses.
47221256Syl150051  * Returns: XGE_HAL_OK - success.
47231256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to disable mcast
47241256Syl150051  * feature within the time(timeout).
47251256Syl150051  *
47261256Syl150051  * See also: xge_hal_device_mcast_enable(), xge_hal_status_e{}.
47271256Syl150051  */
47281256Syl150051 xge_hal_status_e
xge_hal_device_mcast_disable(xge_hal_device_t * hldev)47291256Syl150051 xge_hal_device_mcast_disable(xge_hal_device_t *hldev)
47301256Syl150051 {
47311256Syl150051 	u64 val64;
47321256Syl150051 	xge_hal_pci_bar0_t *bar0;
47333115Syl150051 	int mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET;
47341256Syl150051 
47351256Syl150051 	if (hldev == NULL)
47361256Syl150051 		return XGE_HAL_ERR_INVALID_DEVICE;
47371256Syl150051 
47381256Syl150051 	if (hldev->mcast_refcnt == 0)
47391256Syl150051 		return XGE_HAL_OK;
47401256Syl150051 
47413115Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
47423115Syl150051 		mc_offset = XGE_HAL_MAC_MC_ALL_MC_ADDR_OFFSET_HERC;
47433115Syl150051 
47441256Syl150051 	hldev->mcast_refcnt = 0;
47451256Syl150051 
47461256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
47471256Syl150051 
47481256Syl150051 	/*  Disable all Multicast addresses */
47491256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
47501256Syl150051 	       XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(0xffffffffffffULL),
47511256Syl150051 		       &bar0->rmac_addr_data0_mem);
47521256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
47531256Syl150051 	       XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0),
47541256Syl150051 		       &bar0->rmac_addr_data1_mem);
47551256Syl150051 
47561256Syl150051 	val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_WE |
47571256Syl150051 		XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
47583115Syl150051 		XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET(mc_offset);
47591256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
47601256Syl150051 		            &bar0->rmac_addr_cmd_mem);
47611256Syl150051 
47621256Syl150051 	if (__hal_device_register_poll(hldev,
47631256Syl150051 		&bar0->rmac_addr_cmd_mem, 0,
47641256Syl150051 		XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
47651256Syl150051 		XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
47661256Syl150051 		/* upper layer may require to repeat */
47671256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
47681256Syl150051 	}
47691256Syl150051 
47701256Syl150051 	return XGE_HAL_OK;
47711256Syl150051 }
47721256Syl150051 
47731256Syl150051 /**
47741256Syl150051  * xge_hal_device_promisc_enable - Enable promiscuous mode.
47751256Syl150051  * @hldev: HAL device handle.
47761256Syl150051  *
47771256Syl150051  * Enable promiscuous mode of Xframe operation.
47781256Syl150051  *
47791256Syl150051  * See also: xge_hal_device_promisc_disable().
47801256Syl150051  */
47811256Syl150051 void
xge_hal_device_promisc_enable(xge_hal_device_t * hldev)47821256Syl150051 xge_hal_device_promisc_enable(xge_hal_device_t *hldev)
47831256Syl150051 {
47841256Syl150051 	u64 val64;
47851256Syl150051 	xge_hal_pci_bar0_t *bar0;
47861256Syl150051 
47871256Syl150051 	xge_assert(hldev);
47881256Syl150051 
47891256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
47901256Syl150051 
47911256Syl150051 	if (!hldev->is_promisc) {
47921256Syl150051 		/*  Put the NIC into promiscuous mode */
47931256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
47941256Syl150051 		                            &bar0->mac_cfg);
47951256Syl150051 		val64 |= XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE;
47961256Syl150051 
47971256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
47981256Syl150051 			       XGE_HAL_RMAC_CFG_KEY(0x4C0D),
47991256Syl150051 			       &bar0->rmac_cfg_key);
48001256Syl150051 
48011256Syl150051 		__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
48021256Syl150051 				      (u32)(val64 >> 32),
48031256Syl150051 				      &bar0->mac_cfg);
48041256Syl150051 
48051256Syl150051 		hldev->is_promisc = 1;
48061256Syl150051 		xge_debug_device(XGE_TRACE,
48073115Syl150051 			"mac_cfg 0x"XGE_OS_LLXFMT": promisc enabled",
48081256Syl150051 			(unsigned long long)val64);
48091256Syl150051 	}
48101256Syl150051 }
48111256Syl150051 
48121256Syl150051 /**
48131256Syl150051  * xge_hal_device_promisc_disable - Disable promiscuous mode.
48141256Syl150051  * @hldev: HAL device handle.
48151256Syl150051  *
48161256Syl150051  * Disable promiscuous mode of Xframe operation.
48171256Syl150051  *
48181256Syl150051  * See also: xge_hal_device_promisc_enable().
48191256Syl150051  */
48201256Syl150051 void
xge_hal_device_promisc_disable(xge_hal_device_t * hldev)48211256Syl150051 xge_hal_device_promisc_disable(xge_hal_device_t *hldev)
48221256Syl150051 {
48231256Syl150051 	u64 val64;
48241256Syl150051 	xge_hal_pci_bar0_t *bar0;
48251256Syl150051 
48261256Syl150051 	xge_assert(hldev);
48271256Syl150051 
48281256Syl150051 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
48291256Syl150051 
48301256Syl150051 	if (hldev->is_promisc) {
48311256Syl150051 		/*  Remove the NIC from promiscuous mode */
48321256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
48331256Syl150051 					    &bar0->mac_cfg);
48341256Syl150051 		val64 &= ~XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE;
48351256Syl150051 
48361256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
48371256Syl150051 			       XGE_HAL_RMAC_CFG_KEY(0x4C0D),
48381256Syl150051 			       &bar0->rmac_cfg_key);
48391256Syl150051 
48401256Syl150051 		__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
48411256Syl150051 				      (u32)(val64 >> 32),
48421256Syl150051 				      &bar0->mac_cfg);
48431256Syl150051 
48441256Syl150051 		hldev->is_promisc = 0;
48451256Syl150051 		xge_debug_device(XGE_TRACE,
48463115Syl150051 			"mac_cfg 0x"XGE_OS_LLXFMT": promisc disabled",
48471256Syl150051 			(unsigned long long)val64);
48481256Syl150051 	}
48491256Syl150051 }
48501256Syl150051 
48511256Syl150051 /**
48521256Syl150051  * xge_hal_device_macaddr_get - Get MAC addresses.
48531256Syl150051  * @hldev: HAL device handle.
48541256Syl150051  * @index: MAC address index, in the range from 0 to
48551256Syl150051  * XGE_HAL_MAX_MAC_ADDRESSES.
48561256Syl150051  * @macaddr: MAC address. Returned by HAL.
48571256Syl150051  *
48581256Syl150051  * Retrieve one of the stored MAC addresses by reading non-volatile
48591256Syl150051  * memory on the chip.
48601256Syl150051  *
48611256Syl150051  * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported.
48621256Syl150051  *
48631256Syl150051  * Returns: XGE_HAL_OK - success.
48641256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac
48651256Syl150051  * address within the time(timeout).
48661256Syl150051  * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index.
48671256Syl150051  *
48681256Syl150051  * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}.
48691256Syl150051  */
48701256Syl150051 xge_hal_status_e
xge_hal_device_macaddr_get(xge_hal_device_t * hldev,int index,macaddr_t * macaddr)48711256Syl150051 xge_hal_device_macaddr_get(xge_hal_device_t *hldev, int index,
48721256Syl150051 			macaddr_t *macaddr)
48731256Syl150051 {
48746937Sxw161283 	xge_hal_pci_bar0_t *bar0;
48751256Syl150051 	u64 val64;
48761256Syl150051 	int i;
48771256Syl150051 
48781256Syl150051 	if (hldev == NULL) {
48791256Syl150051 		return XGE_HAL_ERR_INVALID_DEVICE;
48801256Syl150051 	}
48811256Syl150051 
48826937Sxw161283 	bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
48836937Sxw161283 
48841256Syl150051 	if ( index >= XGE_HAL_MAX_MAC_ADDRESSES ) {
48851256Syl150051 		return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES;
48861256Syl150051 	}
48871256Syl150051 
48881256Syl150051 #ifdef XGE_HAL_HERC_EMULATION
48891256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000010000000000,
48901256Syl150051 	                            &bar0->rmac_addr_data0_mem);
48911256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,0x0000000000000000,
48921256Syl150051 	                            &bar0->rmac_addr_data1_mem);
48931256Syl150051     val64 = XGE_HAL_RMAC_ADDR_CMD_MEM_RD |
48941256Syl150051 				 XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
48951256Syl150051 				 XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index));
48961256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
48971256Syl150051 	                     &bar0->rmac_addr_cmd_mem);
48981256Syl150051 
48991256Syl150051 		/* poll until done */
49001256Syl150051 	__hal_device_register_poll(hldev,
49011256Syl150051 		       &bar0->rmac_addr_cmd_mem, 0,
49021256Syl150051 		       XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD,
49031256Syl150051 		       XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS);
49041256Syl150051 
49051256Syl150051 #endif
49061256Syl150051 
49071256Syl150051 	val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_RD |
49081256Syl150051 		  XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
49091256Syl150051 		  XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) );
49101256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
49111256Syl150051 	                     &bar0->rmac_addr_cmd_mem);
49121256Syl150051 
49131256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0,
49141256Syl150051 		   XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
49151256Syl150051 		   XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
49161256Syl150051 		/* upper layer may require to repeat */
49171256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
49181256Syl150051 	}
49191256Syl150051 
49201256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
49211256Syl150051 	                            &bar0->rmac_addr_data0_mem);
49221256Syl150051 	for (i=0; i < XGE_HAL_ETH_ALEN; i++) {
49231256Syl150051 		(*macaddr)[i] = (u8)(val64 >> ((64 - 8) - (i * 8)));
49241256Syl150051 	}
49251256Syl150051 
49261256Syl150051 #ifdef XGE_HAL_HERC_EMULATION
49271256Syl150051 	for (i=0; i < XGE_HAL_ETH_ALEN; i++) {
49281256Syl150051 		(*macaddr)[i] = (u8)0;
49291256Syl150051 	}
49301256Syl150051 	(*macaddr)[1] = (u8)1;
49311256Syl150051 
49321256Syl150051 #endif
49331256Syl150051 
49341256Syl150051 	return XGE_HAL_OK;
49351256Syl150051 }
49361256Syl150051 
49371256Syl150051 /**
49381256Syl150051  * xge_hal_device_macaddr_set - Set MAC address.
49391256Syl150051  * @hldev: HAL device handle.
49401256Syl150051  * @index: MAC address index, in the range from 0 to
49411256Syl150051  * XGE_HAL_MAX_MAC_ADDRESSES.
49421256Syl150051  * @macaddr: New MAC address to configure.
49431256Syl150051  *
49441256Syl150051  * Configure one of the available MAC address "slots".
49451256Syl150051  *
49461256Syl150051  * Up to %XGE_HAL_MAX_MAC_ADDRESSES addresses is supported.
49471256Syl150051  *
49481256Syl150051  * Returns: XGE_HAL_OK - success.
49491256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac
49501256Syl150051  * address within the time(timeout).
49511256Syl150051  * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index.
49521256Syl150051  *
49531256Syl150051  * See also: xge_hal_device_macaddr_get(), xge_hal_status_e{}.
49541256Syl150051  */
49551256Syl150051 xge_hal_status_e
xge_hal_device_macaddr_set(xge_hal_device_t * hldev,int index,macaddr_t macaddr)49561256Syl150051 xge_hal_device_macaddr_set(xge_hal_device_t *hldev, int index,
49571256Syl150051 			macaddr_t macaddr)
49581256Syl150051 {
49591256Syl150051 	xge_hal_pci_bar0_t *bar0 =
49601256Syl150051 		(xge_hal_pci_bar0_t *)(void *)hldev->bar0;
49611256Syl150051 	u64 val64, temp64;
49621256Syl150051 	int i;
49631256Syl150051 
49641256Syl150051 	if ( index >= XGE_HAL_MAX_MAC_ADDRESSES )
49651256Syl150051 		return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES;
49661256Syl150051 
49671256Syl150051 	temp64 = 0;
49681256Syl150051 	for (i=0; i < XGE_HAL_ETH_ALEN; i++) {
49691256Syl150051 		temp64 |= macaddr[i];
49701256Syl150051 		temp64 <<= 8;
49711256Syl150051 	}
49721256Syl150051 	temp64 >>= 8;
49731256Syl150051 
49741256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
49751256Syl150051 	                XGE_HAL_RMAC_ADDR_DATA0_MEM_ADDR(temp64),
49761256Syl150051 		        &bar0->rmac_addr_data0_mem);
49771256Syl150051 
49781256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
49791256Syl150051 	                XGE_HAL_RMAC_ADDR_DATA1_MEM_MASK(0ULL),
49801256Syl150051 		        &bar0->rmac_addr_data1_mem);
49811256Syl150051 
49821256Syl150051 	val64 = ( XGE_HAL_RMAC_ADDR_CMD_MEM_WE |
49831256Syl150051 		  XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
49841256Syl150051 		  XGE_HAL_RMAC_ADDR_CMD_MEM_OFFSET((index)) );
49851256Syl150051 
49861256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
49871256Syl150051 	                     &bar0->rmac_addr_cmd_mem);
49881256Syl150051 
49891256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->rmac_addr_cmd_mem, 0,
49901256Syl150051 		   XGE_HAL_RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
49911256Syl150051 		   XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
49921256Syl150051 		/* upper layer may require to repeat */
49931256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
49941256Syl150051 	}
49951256Syl150051 
49961256Syl150051 	return XGE_HAL_OK;
49971256Syl150051 }
49981256Syl150051 
49991256Syl150051 /**
50006937Sxw161283  * xge_hal_device_macaddr_clear - Set MAC address.
50016937Sxw161283  * @hldev: HAL device handle.
50026937Sxw161283  * @index: MAC address index, in the range from 0 to
50036937Sxw161283  * XGE_HAL_MAX_MAC_ADDRESSES.
50046937Sxw161283  *
50056937Sxw161283  * Clear one of the available MAC address "slots".
50066937Sxw161283  *
50076937Sxw161283  * Returns: XGE_HAL_OK - success.
50086937Sxw161283  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to set the new mac
50096937Sxw161283  * address within the time(timeout).
50106937Sxw161283  * XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES - Invalid MAC address index.
50116937Sxw161283  *
50126937Sxw161283  * See also: xge_hal_device_macaddr_set(), xge_hal_status_e{}.
50136937Sxw161283  */
50146937Sxw161283 xge_hal_status_e
xge_hal_device_macaddr_clear(xge_hal_device_t * hldev,int index)50156937Sxw161283 xge_hal_device_macaddr_clear(xge_hal_device_t *hldev, int index)
50166937Sxw161283 {
50176937Sxw161283 	xge_hal_status_e status;
50186937Sxw161283 	u8 macaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
50196937Sxw161283 
50206937Sxw161283 	status = xge_hal_device_macaddr_set(hldev, index, macaddr);
50216937Sxw161283 	if (status != XGE_HAL_OK) {
50226937Sxw161283 		xge_debug_device(XGE_ERR, "%s",
50236937Sxw161283 			"Not able to set the mac addr");
50246937Sxw161283 		return status;
50256937Sxw161283 	}
50266937Sxw161283 
50276937Sxw161283 	return XGE_HAL_OK;
50286937Sxw161283 }
50296937Sxw161283 
50306937Sxw161283 /**
50311256Syl150051  * xge_hal_device_macaddr_find - Finds index in the rmac table.
50321256Syl150051  * @hldev: HAL device handle.
50331256Syl150051  * @wanted: Wanted MAC address.
50341256Syl150051  *
50351256Syl150051  * See also: xge_hal_device_macaddr_set().
50361256Syl150051  */
50371256Syl150051 int
xge_hal_device_macaddr_find(xge_hal_device_t * hldev,macaddr_t wanted)50381256Syl150051 xge_hal_device_macaddr_find(xge_hal_device_t *hldev, macaddr_t wanted)
50391256Syl150051 {
50401256Syl150051 	int i;
50416937Sxw161283 	macaddr_t macaddr;
50421256Syl150051 
50431256Syl150051 	if (hldev == NULL) {
50441256Syl150051 		return XGE_HAL_ERR_INVALID_DEVICE;
50451256Syl150051 	}
50461256Syl150051 
5047*8275SEric Cheng 	for (i=0; i<XGE_HAL_MAX_MAC_ADDRESSES; i++) {
50481256Syl150051 		(void) xge_hal_device_macaddr_get(hldev, i, &macaddr);
50491256Syl150051 		if (!xge_os_memcmp(macaddr, wanted, sizeof(macaddr_t))) {
50501256Syl150051 			return i;
50511256Syl150051 		}
50521256Syl150051 	}
50531256Syl150051 
50541256Syl150051 	return -1;
50551256Syl150051 }
50561256Syl150051 
50571256Syl150051 /**
50581256Syl150051  * xge_hal_device_mtu_set - Set MTU.
50591256Syl150051  * @hldev: HAL device handle.
50601256Syl150051  * @new_mtu: New MTU size to configure.
50611256Syl150051  *
50621256Syl150051  * Set new MTU value. Example, to use jumbo frames:
50631256Syl150051  * xge_hal_device_mtu_set(my_device, my_channel, 9600);
50641256Syl150051  *
50651256Syl150051  * Returns: XGE_HAL_OK on success.
50661256Syl150051  * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control
50671256Syl150051  * register.
50681256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to initialize TTI/RTI
50691256Syl150051  * schemes.
50701256Syl150051  * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT - Failed to restore the device to
50711256Syl150051  * a "quiescent" state.
50721256Syl150051  */
50731256Syl150051 xge_hal_status_e
xge_hal_device_mtu_set(xge_hal_device_t * hldev,int new_mtu)50741256Syl150051 xge_hal_device_mtu_set(xge_hal_device_t *hldev, int new_mtu)
50751256Syl150051 {
50761256Syl150051 	xge_hal_status_e status;
50771256Syl150051 
50781256Syl150051 	/*
50791256Syl150051 	 * reset needed if 1) new MTU differs, and
50801256Syl150051 	 * 2a) device was closed or
50811256Syl150051 	 * 2b) device is being upped for first time.
50821256Syl150051 	 */
50831256Syl150051 	if (hldev->config.mtu != new_mtu) {
50841256Syl150051 		if (hldev->reset_needed_after_close ||
50851256Syl150051 			!hldev->mtu_first_time_set) {
50861256Syl150051 			status = xge_hal_device_reset(hldev);
50871256Syl150051 			if (status != XGE_HAL_OK) {
50881256Syl150051 				xge_debug_device(XGE_TRACE, "%s",
50891256Syl150051 					  "fatal: can not reset the device");
50901256Syl150051 				return status;
50911256Syl150051 			}
50921256Syl150051 		}
50931256Syl150051 		/* store the new MTU in device, reset will use it */
50941256Syl150051 		hldev->config.mtu = new_mtu;
50951256Syl150051 		xge_debug_device(XGE_TRACE, "new MTU %d applied",
50961256Syl150051 				 new_mtu);
50971256Syl150051 	}
50981256Syl150051 
50991256Syl150051 	if (!hldev->mtu_first_time_set)
51001256Syl150051 		hldev->mtu_first_time_set = 1;
51011256Syl150051 
51021256Syl150051 	return XGE_HAL_OK;
51031256Syl150051 }
51041256Syl150051 
51051256Syl150051 /**
51061256Syl150051  * xge_hal_device_initialize - Initialize Xframe device.
51071256Syl150051  * @hldev: HAL device handle.
51081256Syl150051  * @attr: pointer to xge_hal_device_attr_t structure
51091256Syl150051  * @device_config: Configuration to be _applied_ to the device,
51101256Syl150051  *                 For the Xframe configuration "knobs" please
51111256Syl150051  *                 refer to xge_hal_device_config_t and Xframe
51121256Syl150051  *                 User Guide.
51131256Syl150051  *
51141256Syl150051  * Initialize Xframe device. Note that all the arguments of this public API
51151256Syl150051  * are 'IN', including @hldev. Upper-layer driver (ULD) cooperates with
51161256Syl150051  * OS to find new Xframe device, locate its PCI and memory spaces.
51171256Syl150051  *
51181256Syl150051  * When done, the ULD allocates sizeof(xge_hal_device_t) bytes for HAL
51191256Syl150051  * to enable the latter to perform Xframe hardware initialization.
51201256Syl150051  *
51211256Syl150051  * Returns: XGE_HAL_OK - success.
51221256Syl150051  * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - Driver is not initialized.
51231256Syl150051  * XGE_HAL_ERR_BAD_DEVICE_CONFIG - Device configuration params are not
51241256Syl150051  * valid.
51251256Syl150051  * XGE_HAL_ERR_OUT_OF_MEMORY - Memory allocation failed.
51261256Syl150051  * XGE_HAL_ERR_BAD_SUBSYSTEM_ID - Device subsystem id is invalid.
51271256Syl150051  * XGE_HAL_ERR_INVALID_MAC_ADDRESS - Device mac address in not valid.
51281256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to retrieve the mac
51291256Syl150051  * address within the time(timeout) or TTI/RTI initialization failed.
51301256Syl150051  * XGE_HAL_ERR_SWAPPER_CTRL - Failed to configure swapper control.
51311256Syl150051  * XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT -Device is not queiscent.
51321256Syl150051  *
51331256Syl150051  * See also: xge_hal_device_terminate(), xge_hal_status_e{}
51341256Syl150051  * xge_hal_device_attr_t{}.
51351256Syl150051  */
51361256Syl150051 xge_hal_status_e
xge_hal_device_initialize(xge_hal_device_t * hldev,xge_hal_device_attr_t * attr,xge_hal_device_config_t * device_config)51371256Syl150051 xge_hal_device_initialize(xge_hal_device_t *hldev, xge_hal_device_attr_t *attr,
51381256Syl150051 		xge_hal_device_config_t *device_config)
51391256Syl150051 {
51401256Syl150051 	int i;
51411256Syl150051 	xge_hal_status_e status;
51421256Syl150051 	xge_hal_channel_t *channel;
51431256Syl150051 	u16 subsys_device;
51441256Syl150051 	u16 subsys_vendor;
51451256Syl150051 	int total_dram_size, ring_auto_dram_cfg, left_dram_size;
51461256Syl150051 	int total_dram_size_max = 0;
51471256Syl150051 
51483115Syl150051 	xge_debug_device(XGE_TRACE, "device 0x"XGE_OS_LLXFMT" is initializing",
51491256Syl150051 			 (unsigned long long)(ulong_t)hldev);
51501256Syl150051 
51511256Syl150051 	/* sanity check */
51521256Syl150051 	if (g_xge_hal_driver == NULL ||
51531256Syl150051 	    !g_xge_hal_driver->is_initialized) {
51541256Syl150051 		return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED;
51551256Syl150051 	}
51561256Syl150051 
51571256Syl150051 	xge_os_memzero(hldev, sizeof(xge_hal_device_t));
51581256Syl150051 
51591256Syl150051 	/*
51601256Syl150051 	 * validate a common part of Xframe-I/II configuration
51611256Syl150051 	 * (and run check_card() later, once PCI inited - see below)
51621256Syl150051 	 */
51631256Syl150051 	status = __hal_device_config_check_common(device_config);
51641256Syl150051 	if (status != XGE_HAL_OK)
51651256Syl150051 		return status;
51661256Syl150051 
51671256Syl150051 	/* apply config */
51681256Syl150051 	xge_os_memcpy(&hldev->config, device_config,
51691256Syl150051                       sizeof(xge_hal_device_config_t));
51701256Syl150051 
51711256Syl150051 	/* save original attr */
51721256Syl150051 	xge_os_memcpy(&hldev->orig_attr, attr,
51731256Syl150051                       sizeof(xge_hal_device_attr_t));
51741256Syl150051 
51751256Syl150051 	/* initialize rxufca_intr_thres */
51761256Syl150051 	hldev->rxufca_intr_thres = hldev->config.rxufca_intr_thres;
51771256Syl150051 
51781256Syl150051 	hldev->regh0 = attr->regh0;
51791256Syl150051 	hldev->regh1 = attr->regh1;
51801256Syl150051 	hldev->regh2 = attr->regh2;
51811256Syl150051 	hldev->isrbar0 = hldev->bar0 = attr->bar0;
51821256Syl150051 	hldev->bar1 = attr->bar1;
51831256Syl150051 	hldev->bar2 = attr->bar2;
51841256Syl150051 	hldev->pdev = attr->pdev;
51851256Syl150051 	hldev->irqh = attr->irqh;
51861256Syl150051 	hldev->cfgh = attr->cfgh;
51871256Syl150051 
51883115Syl150051 	/* set initial bimodal timer for bimodal adaptive schema */
51893115Syl150051 	hldev->bimodal_timer_val_us = hldev->config.bimodal_timer_lo_us;
51903115Syl150051 
51911256Syl150051 	hldev->queueh = xge_queue_create(hldev->pdev, hldev->irqh,
51921256Syl150051 				  g_xge_hal_driver->config.queue_size_initial,
51931256Syl150051 				  g_xge_hal_driver->config.queue_size_max,
51941256Syl150051 				  __hal_device_event_queued, hldev);
51951256Syl150051 	if (hldev->queueh == NULL)
51961256Syl150051 		return XGE_HAL_ERR_OUT_OF_MEMORY;
51971256Syl150051 
51981256Syl150051 	hldev->magic = XGE_HAL_MAGIC;
51991256Syl150051 
52001256Syl150051 	xge_assert(hldev->regh0);
52011256Syl150051 	xge_assert(hldev->regh1);
52021256Syl150051 	xge_assert(hldev->bar0);
52031256Syl150051 	xge_assert(hldev->bar1);
52041256Syl150051 	xge_assert(hldev->pdev);
52051256Syl150051 	xge_assert(hldev->irqh);
52061256Syl150051 	xge_assert(hldev->cfgh);
52071256Syl150051 
52081256Syl150051 	/* initialize some PCI/PCI-X fields of this PCI device. */
52091256Syl150051 	__hal_device_pci_init(hldev);
52101256Syl150051 
52111256Syl150051 	/*
52121256Syl150051 	 * initlialize lists to properly handling a potential
52131256Syl150051 	 * terminate request
52141256Syl150051 	 */
52151256Syl150051 	xge_list_init(&hldev->free_channels);
52161256Syl150051 	xge_list_init(&hldev->fifo_channels);
52171256Syl150051 	xge_list_init(&hldev->ring_channels);
52181256Syl150051 
52191256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) {
52201256Syl150051 		/* fixups for xena */
52211256Syl150051 		hldev->config.rth_en = 0;
52221256Syl150051 		hldev->config.rth_spdm_en = 0;
52231256Syl150051 		hldev->config.rts_mac_en = 0;
52241256Syl150051 		total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_XENA;
52251256Syl150051 
52261256Syl150051 		status = __hal_device_config_check_xena(device_config);
52271256Syl150051 		if (status != XGE_HAL_OK) {
52281256Syl150051 			xge_hal_device_terminate(hldev);
52291256Syl150051 			return status;
52301256Syl150051 		}
52313115Syl150051 		if (hldev->config.bimodal_interrupts == 1) {
52323115Syl150051 			xge_hal_device_terminate(hldev);
52333115Syl150051 			return XGE_HAL_BADCFG_BIMODAL_XENA_NOT_ALLOWED;
52343115Syl150051 		} else if (hldev->config.bimodal_interrupts ==
52353115Syl150051 		    XGE_HAL_DEFAULT_USE_HARDCODE)
52363115Syl150051 			hldev->config.bimodal_interrupts = 0;
52371256Syl150051 	} else if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC) {
52381256Syl150051 		/* fixups for herc */
52391256Syl150051 		total_dram_size_max = XGE_HAL_MAX_RING_QUEUE_SIZE_HERC;
52401256Syl150051 		status = __hal_device_config_check_herc(device_config);
52411256Syl150051 		if (status != XGE_HAL_OK) {
52421256Syl150051 			xge_hal_device_terminate(hldev);
52431256Syl150051 			return status;
52441256Syl150051 		}
52453115Syl150051 		if (hldev->config.bimodal_interrupts ==
52463115Syl150051 		    XGE_HAL_DEFAULT_USE_HARDCODE)
52473115Syl150051 			hldev->config.bimodal_interrupts = 1;
52481256Syl150051 	} else {
52491256Syl150051 		xge_debug_device(XGE_ERR,
52501256Syl150051 			  "detected unknown device_id 0x%x", hldev->device_id);
52511256Syl150051 		xge_hal_device_terminate(hldev);
52521256Syl150051 		return XGE_HAL_ERR_BAD_DEVICE_ID;
52531256Syl150051 	}
52541256Syl150051 
52553115Syl150051 
52561256Syl150051 	/* allocate and initialize FIFO types of channels according to
52571256Syl150051 	 * configuration */
52581256Syl150051 	for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) {
52591256Syl150051 		if (!device_config->fifo.queue[i].configured)
52601256Syl150051 			continue;
52611256Syl150051 
52621256Syl150051 		channel = __hal_channel_allocate(hldev, i,
52631256Syl150051 						 XGE_HAL_CHANNEL_TYPE_FIFO);
52641256Syl150051 		if (channel == NULL) {
52651256Syl150051 			xge_debug_device(XGE_ERR,
52661256Syl150051 				"fifo: __hal_channel_allocate failed");
52671256Syl150051 			xge_hal_device_terminate(hldev);
52681256Syl150051 			return XGE_HAL_ERR_OUT_OF_MEMORY;
52691256Syl150051 		}
52701256Syl150051 		/* add new channel to the device */
52711256Syl150051 		xge_list_insert(&channel->item, &hldev->free_channels);
52721256Syl150051 	}
52731256Syl150051 
52741256Syl150051 	/*
52751256Syl150051 	 * automatic DRAM adjustment
52761256Syl150051 	 */
52771256Syl150051 	total_dram_size = 0;
52781256Syl150051 	ring_auto_dram_cfg = 0;
52791256Syl150051 	for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) {
52801256Syl150051 		if (!device_config->ring.queue[i].configured)
52811256Syl150051 			continue;
52821256Syl150051 		if (device_config->ring.queue[i].dram_size_mb ==
52831256Syl150051 		    XGE_HAL_DEFAULT_USE_HARDCODE) {
52841256Syl150051 			ring_auto_dram_cfg++;
52851256Syl150051 			continue;
52861256Syl150051 		}
52871256Syl150051 		total_dram_size += device_config->ring.queue[i].dram_size_mb;
52881256Syl150051 	}
52891256Syl150051 	left_dram_size = total_dram_size_max - total_dram_size;
52901256Syl150051 	if (left_dram_size < 0 ||
52911256Syl150051 	    (ring_auto_dram_cfg && left_dram_size / ring_auto_dram_cfg == 0))  {
52921256Syl150051 		xge_debug_device(XGE_ERR,
52931256Syl150051 			 "ring config: exceeded DRAM size %d MB",
52941256Syl150051 			 total_dram_size_max);
52951256Syl150051 		xge_hal_device_terminate(hldev);
52961256Syl150051                 return XGE_HAL_BADCFG_RING_QUEUE_SIZE;
52971256Syl150051         }
52981256Syl150051 
52991256Syl150051 	/*
53001256Syl150051 	 * allocate and initialize RING types of channels according to
53011256Syl150051 	 * configuration
53021256Syl150051 	 */
53031256Syl150051 	for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) {
53041256Syl150051 		if (!device_config->ring.queue[i].configured)
53051256Syl150051 			continue;
53061256Syl150051 
53071256Syl150051 		if (device_config->ring.queue[i].dram_size_mb ==
53081256Syl150051 		    XGE_HAL_DEFAULT_USE_HARDCODE) {
53091256Syl150051 			hldev->config.ring.queue[i].dram_size_mb =
53101256Syl150051 				device_config->ring.queue[i].dram_size_mb =
53111256Syl150051 					left_dram_size / ring_auto_dram_cfg;
53121256Syl150051 		}
53131256Syl150051 
53141256Syl150051 		channel = __hal_channel_allocate(hldev, i,
53156937Sxw161283 						 XGE_HAL_CHANNEL_TYPE_RING);
53161256Syl150051 		if (channel == NULL) {
53171256Syl150051 			xge_debug_device(XGE_ERR,
53181256Syl150051 				"ring: __hal_channel_allocate failed");
53191256Syl150051 			xge_hal_device_terminate(hldev);
53201256Syl150051 			return XGE_HAL_ERR_OUT_OF_MEMORY;
53211256Syl150051 		}
53221256Syl150051 		/* add new channel to the device */
53231256Syl150051 		xge_list_insert(&channel->item, &hldev->free_channels);
53241256Syl150051 	}
53251256Syl150051 
53261256Syl150051 	/* get subsystem IDs */
53271256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
53281256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, subsystem_id),
53291256Syl150051 		&subsys_device);
53301256Syl150051 	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
53311256Syl150051 		xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id),
53321256Syl150051 		&subsys_vendor);
53331256Syl150051 	xge_debug_device(XGE_TRACE,
53341256Syl150051                          "subsystem_id %04x:%04x",
53351256Syl150051                          subsys_vendor, subsys_device);
53361256Syl150051 
53371256Syl150051 	/* reset device initially */
53381256Syl150051 	(void) __hal_device_reset(hldev);
53391256Syl150051 
53401256Syl150051 	/* set host endian before, to assure proper action */
53411256Syl150051 	status = __hal_device_set_swapper(hldev);
53421256Syl150051 	if (status != XGE_HAL_OK) {
53431256Syl150051 		xge_debug_device(XGE_ERR,
53441256Syl150051 			"__hal_device_set_swapper failed");
53451256Syl150051 		xge_hal_device_terminate(hldev);
53461256Syl150051 		(void) __hal_device_reset(hldev);
53471256Syl150051 		return status;
53481256Syl150051 	}
53491256Syl150051 
53501256Syl150051 #ifndef XGE_HAL_HERC_EMULATION
53511256Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA)
53521256Syl150051 		__hal_device_xena_fix_mac(hldev);
53531256Syl150051 #endif
53541256Syl150051 
53551256Syl150051 	/*  MAC address initialization.
53561256Syl150051 	 *  For now only one mac address will be read and used.  */
53571256Syl150051 	status = xge_hal_device_macaddr_get(hldev, 0, &hldev->macaddr[0]);
53581256Syl150051 	if (status != XGE_HAL_OK) {
53591256Syl150051 		xge_debug_device(XGE_ERR,
53601256Syl150051 			"xge_hal_device_macaddr_get failed");
53611256Syl150051 		xge_hal_device_terminate(hldev);
53621256Syl150051 		return status;
53631256Syl150051 	}
53641256Syl150051 
53651256Syl150051 	if (hldev->macaddr[0][0] == 0xFF &&
53661256Syl150051 	    hldev->macaddr[0][1] == 0xFF &&
53671256Syl150051 	    hldev->macaddr[0][2] == 0xFF &&
53681256Syl150051 	    hldev->macaddr[0][3] == 0xFF &&
53691256Syl150051 	    hldev->macaddr[0][4] == 0xFF &&
53701256Syl150051 	    hldev->macaddr[0][5] == 0xFF) {
53711256Syl150051 		xge_debug_device(XGE_ERR,
53721256Syl150051 			"xge_hal_device_macaddr_get returns all FFs");
53731256Syl150051 		xge_hal_device_terminate(hldev);
53741256Syl150051 		return XGE_HAL_ERR_INVALID_MAC_ADDRESS;
53751256Syl150051 	}
53761256Syl150051 
53771256Syl150051 	xge_debug_device(XGE_TRACE,
53781256Syl150051 			  "default macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x",
53791256Syl150051 			  hldev->macaddr[0][0], hldev->macaddr[0][1],
53801256Syl150051 			  hldev->macaddr[0][2], hldev->macaddr[0][3],
53811256Syl150051 			  hldev->macaddr[0][4], hldev->macaddr[0][5]);
53821256Syl150051 
53831256Syl150051 	status = __hal_stats_initialize(&hldev->stats, hldev);
53841256Syl150051 	if (status != XGE_HAL_OK) {
53851256Syl150051 		xge_debug_device(XGE_ERR,
53861256Syl150051 			"__hal_stats_initialize failed");
53871256Syl150051 		xge_hal_device_terminate(hldev);
53881256Syl150051 		return status;
53891256Syl150051 	}
53901256Syl150051 
53911256Syl150051 	status = __hal_device_hw_initialize(hldev);
53921256Syl150051 	if (status != XGE_HAL_OK) {
53931256Syl150051 		xge_debug_device(XGE_ERR,
53941256Syl150051 			"__hal_device_hw_initialize failed");
53951256Syl150051 		xge_hal_device_terminate(hldev);
53961256Syl150051 		return status;
53971256Syl150051 	}
53983115Syl150051 	hldev->dump_buf=(char*)xge_os_malloc(hldev->pdev, XGE_HAL_DUMP_BUF_SIZE);
53991256Syl150051 	if (hldev->dump_buf == NULL)  {
54001256Syl150051 		xge_debug_device(XGE_ERR,
54011256Syl150051 			"__hal_device_hw_initialize failed");
54021256Syl150051 		xge_hal_device_terminate(hldev);
54031256Syl150051                 return XGE_HAL_ERR_OUT_OF_MEMORY;
54041256Syl150051 	}
54051256Syl150051 
54061256Syl150051 
54071256Syl150051 	/* Xena-only: need to serialize fifo posts across all device fifos */
54081256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
54091256Syl150051 	xge_os_spin_lock_init(&hldev->xena_post_lock, hldev->pdev);
54101256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
54111256Syl150051 	xge_os_spin_lock_init_irq(&hldev->xena_post_lock, hldev->irqh);
54121256Syl150051 #endif
54136937Sxw161283 	 /* Getting VPD data */
54146937Sxw161283         __hal_device_get_vpd_data(hldev);
54156937Sxw161283 
54161256Syl150051 	hldev->is_initialized = 1;
54171256Syl150051 
54181256Syl150051 	return XGE_HAL_OK;
54191256Syl150051 }
54201256Syl150051 
54211256Syl150051 /**
54221256Syl150051  * xge_hal_device_terminating - Mark the device as 'terminating'.
54231256Syl150051  * @devh: HAL device handle.
54241256Syl150051  *
54251256Syl150051  * Mark the device as 'terminating', going to terminate. Can be used
54261256Syl150051  * to serialize termination with other running processes/contexts.
54271256Syl150051  *
54281256Syl150051  * See also: xge_hal_device_terminate().
54291256Syl150051  */
54301256Syl150051 void
xge_hal_device_terminating(xge_hal_device_h devh)54311256Syl150051 xge_hal_device_terminating(xge_hal_device_h devh)
54321256Syl150051 {
54331256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
54346937Sxw161283 	xge_list_t *item;
54356937Sxw161283 	xge_hal_channel_t *channel;
54366937Sxw161283 #if defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
54376937Sxw161283 	unsigned long flags = 0;
54386937Sxw161283 #endif
54396937Sxw161283 
54406937Sxw161283 	/*
54416937Sxw161283 	 * go through each opened tx channel and aquire
54426937Sxw161283 	 * lock, so it will serialize with HAL termination flag
54436937Sxw161283 	 */
54446937Sxw161283 	xge_list_for_each(item, &hldev->fifo_channels) {
54456937Sxw161283 		channel = xge_container_of(item, xge_hal_channel_t, item);
54466937Sxw161283 #if defined(XGE_HAL_TX_MULTI_RESERVE)
54476937Sxw161283 	xge_os_spin_lock(&channel->reserve_lock);
54486937Sxw161283 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
54496937Sxw161283 	xge_os_spin_lock_irq(&channel->reserve_lock, flags);
54506937Sxw161283 #endif
54516937Sxw161283 
54526937Sxw161283 	channel->terminating = 1;
54536937Sxw161283 
54546937Sxw161283 #if defined(XGE_HAL_TX_MULTI_RESERVE)
54556937Sxw161283 	xge_os_spin_unlock(&channel->reserve_lock);
54566937Sxw161283 #elif defined(XGE_HAL_TX_MULTI_RESERVE_IRQ)
54576937Sxw161283 	xge_os_spin_unlock_irq(&channel->reserve_lock, flags);
54586937Sxw161283 #endif
54596937Sxw161283 	}
54606937Sxw161283 
54611256Syl150051 	hldev->terminating = 1;
54621256Syl150051 }
54631256Syl150051 
54641256Syl150051 /**
54651256Syl150051  * xge_hal_device_terminate - Terminate Xframe device.
54661256Syl150051  * @hldev: HAL device handle.
54671256Syl150051  *
54681256Syl150051  * Terminate HAL device.
54691256Syl150051  *
54701256Syl150051  * See also: xge_hal_device_initialize().
54711256Syl150051  */
54721256Syl150051 void
xge_hal_device_terminate(xge_hal_device_t * hldev)54731256Syl150051 xge_hal_device_terminate(xge_hal_device_t *hldev)
54741256Syl150051 {
54751256Syl150051 	xge_assert(g_xge_hal_driver != NULL);
54761256Syl150051 	xge_assert(hldev != NULL);
54771256Syl150051 	xge_assert(hldev->magic == XGE_HAL_MAGIC);
54781256Syl150051 
54791256Syl150051 	xge_queue_flush(hldev->queueh);
54801256Syl150051 
54811256Syl150051 	hldev->terminating = 1;
54821256Syl150051 	hldev->is_initialized = 0;
54831256Syl150051         hldev->in_poll = 0;
54841256Syl150051 	hldev->magic = XGE_HAL_DEAD;
54851256Syl150051 
54861256Syl150051 #if defined(XGE_HAL_TX_MULTI_POST)
54871256Syl150051 	xge_os_spin_lock_destroy(&hldev->xena_post_lock, hldev->pdev);
54881256Syl150051 #elif defined(XGE_HAL_TX_MULTI_POST_IRQ)
54891256Syl150051 	xge_os_spin_lock_destroy_irq(&hldev->xena_post_lock, hldev->pdev);
54901256Syl150051 #endif
54911256Syl150051 
54923115Syl150051 	xge_debug_device(XGE_TRACE, "device "XGE_OS_LLXFMT" is terminating",
54931256Syl150051 				(unsigned long long)(ulong_t)hldev);
54941256Syl150051 
54951256Syl150051 	xge_assert(xge_list_is_empty(&hldev->fifo_channels));
54961256Syl150051 	xge_assert(xge_list_is_empty(&hldev->ring_channels));
54971256Syl150051 
54981256Syl150051 	if (hldev->stats.is_initialized) {
54991256Syl150051 		__hal_stats_terminate(&hldev->stats);
55001256Syl150051 	}
55011256Syl150051 
55021256Syl150051 	/* close if open and free all channels */
55031256Syl150051 	while (!xge_list_is_empty(&hldev->free_channels)) {
55041256Syl150051 		xge_hal_channel_t *channel = (xge_hal_channel_t*)
55051256Syl150051 					hldev->free_channels.next;
55061256Syl150051 
55071256Syl150051 		xge_assert(!channel->is_open);
55081256Syl150051 		xge_list_remove(&channel->item);
55091256Syl150051 		__hal_channel_free(channel);
55101256Syl150051 	}
55111256Syl150051 
55121256Syl150051 	if (hldev->queueh) {
55131256Syl150051 		xge_queue_destroy(hldev->queueh);
55141256Syl150051 	}
55151256Syl150051 
55161256Syl150051 	if (hldev->spdm_table) {
55171256Syl150051 		xge_os_free(hldev->pdev,
55181256Syl150051 			  hldev->spdm_table[0],
55191256Syl150051 			  (sizeof(xge_hal_spdm_entry_t) *
55201256Syl150051 				hldev->spdm_max_entries));
55211256Syl150051 		xge_os_free(hldev->pdev,
55221256Syl150051 			  hldev->spdm_table,
55231256Syl150051 			  (sizeof(xge_hal_spdm_entry_t *) *
55241256Syl150051 				hldev->spdm_max_entries));
55251256Syl150051 		xge_os_spin_lock_destroy(&hldev->spdm_lock, hldev->pdev);
55261256Syl150051 		hldev->spdm_table = NULL;
55271256Syl150051 	}
55281256Syl150051 
55291256Syl150051 	if (hldev->dump_buf)  {
55301256Syl150051 	        xge_os_free(hldev->pdev, hldev->dump_buf,
55311256Syl150051 			    XGE_HAL_DUMP_BUF_SIZE);
55321256Syl150051 		hldev->dump_buf = NULL;
55331256Syl150051 	}
55343115Syl150051 
55356937Sxw161283 	if (hldev->device_id != 0) {
55366937Sxw161283 		int j, pcisize;
55376937Sxw161283 
55386937Sxw161283 		pcisize = (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)?
55396937Sxw161283 				   XGE_HAL_PCISIZE_HERC : XGE_HAL_PCISIZE_XENA;
55406937Sxw161283 		for (j = 0; j < pcisize; j++) {
55416937Sxw161283 			xge_os_pci_write32(hldev->pdev, hldev->cfgh, j * 4,
55426937Sxw161283 				*((u32*)&hldev->pci_config_space_bios + j));
55436937Sxw161283 		}
55446937Sxw161283 	}
55451256Syl150051 }
55466937Sxw161283 /**
55476937Sxw161283  * __hal_device_get_vpd_data - Getting vpd_data.
55486937Sxw161283  *
55496937Sxw161283  *   @hldev: HAL device handle.
55506937Sxw161283  *
55516937Sxw161283  *   Getting  product name and serial number from vpd capabilites structure
55526937Sxw161283  *
55536937Sxw161283  */
55546937Sxw161283 void
__hal_device_get_vpd_data(xge_hal_device_t * hldev)55556937Sxw161283 __hal_device_get_vpd_data(xge_hal_device_t *hldev)
55566937Sxw161283 {
55576937Sxw161283     u8 * vpd_data;
55586937Sxw161283     u8   data;
55596937Sxw161283     int  index = 0, count, fail = 0;
55606937Sxw161283     u8   vpd_addr = XGE_HAL_CARD_XENA_VPD_ADDR;
55616937Sxw161283     if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
55626937Sxw161283         vpd_addr = XGE_HAL_CARD_HERC_VPD_ADDR;
55636937Sxw161283 
55646937Sxw161283     xge_os_strlcpy((char *) hldev->vpd_data.product_name,
55656937Sxw161283                 "10 Gigabit Ethernet Adapter",
55666937Sxw161283 		sizeof(hldev->vpd_data.product_name));
55676937Sxw161283 
55686937Sxw161283     xge_os_strlcpy((char *) hldev->vpd_data.serial_num,
55696937Sxw161283 		"not available",
55706937Sxw161283 		sizeof(hldev->vpd_data.serial_num));
55716937Sxw161283 
55726937Sxw161283     vpd_data = ( u8*) xge_os_malloc(hldev->pdev, XGE_HAL_VPD_BUFFER_SIZE + 16);
55736937Sxw161283     if ( vpd_data == 0 )
55746937Sxw161283         return;
55756937Sxw161283 
55766937Sxw161283     for (index = 0; index < XGE_HAL_VPD_BUFFER_SIZE; index +=4 ) {
55776937Sxw161283         xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 2), (u8)index);
55786937Sxw161283         xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 2), &data);
55796937Sxw161283         xge_os_pci_write8(hldev->pdev, hldev->cfgh, (vpd_addr + 3), 0);
55806937Sxw161283         for (count = 0; count < 5; count++ ) {
55816937Sxw161283             xge_os_mdelay(2);
55826937Sxw161283             xge_os_pci_read8(hldev->pdev, hldev->cfgh,(vpd_addr + 3), &data);
55836937Sxw161283             if (data == XGE_HAL_VPD_READ_COMPLETE)
55846937Sxw161283                 break;
55856937Sxw161283         }
55866937Sxw161283 
55876937Sxw161283         if (count >= 5) {
55886937Sxw161283             xge_os_printf("ERR, Reading VPD data failed");
55896937Sxw161283             fail = 1;
55906937Sxw161283             break;
55916937Sxw161283         }
55926937Sxw161283 
55936937Sxw161283         xge_os_pci_read32(hldev->pdev, hldev->cfgh,(vpd_addr + 4),
55946937Sxw161283                 (u32 *)&vpd_data[index]);
55956937Sxw161283     }
55966937Sxw161283 
55976937Sxw161283     if(!fail) {
55986937Sxw161283 
55996937Sxw161283         /* read serial number of adapter */
56006937Sxw161283         for (count = 0; count < XGE_HAL_VPD_BUFFER_SIZE; count++) {
56016937Sxw161283             if ((vpd_data[count] == 'S')     &&
56026937Sxw161283                 (vpd_data[count + 1] == 'N') &&
56036937Sxw161283                 (vpd_data[count + 2] < XGE_HAL_VPD_LENGTH)) {
56046937Sxw161283                     (void) memset(hldev->vpd_data.serial_num, 0, XGE_HAL_VPD_LENGTH);
56056937Sxw161283                     (void) memcpy(hldev->vpd_data.serial_num, &vpd_data[count + 3],
56066937Sxw161283                         vpd_data[count + 2]);
56076937Sxw161283                     break;
56086937Sxw161283             }
56096937Sxw161283         }
56106937Sxw161283 
56116937Sxw161283         if (vpd_data[1] < XGE_HAL_VPD_LENGTH) {
56126937Sxw161283             (void) memset(hldev->vpd_data.product_name, 0, vpd_data[1]);
56136937Sxw161283             (void) memcpy(hldev->vpd_data.product_name, &vpd_data[3], vpd_data[1]);
56146937Sxw161283         }
56156937Sxw161283 
56166937Sxw161283     }
56176937Sxw161283 
56186937Sxw161283     xge_os_free(hldev->pdev, vpd_data, XGE_HAL_VPD_BUFFER_SIZE + 16);
56196937Sxw161283 }
56206937Sxw161283 
56216937Sxw161283 
56221256Syl150051 /**
56231256Syl150051  * xge_hal_device_handle_tcode - Handle transfer code.
56241256Syl150051  * @channelh: Channel handle.
56251256Syl150051  * @dtrh: Descriptor handle.
56261256Syl150051  * @t_code: One of the enumerated (and documented in the Xframe user guide)
56271256Syl150051  *          "transfer codes".
56281256Syl150051  *
56291256Syl150051  * Handle descriptor's transfer code. The latter comes with each completed
56301256Syl150051  * descriptor, see xge_hal_fifo_dtr_next_completed() and
56311256Syl150051  * xge_hal_ring_dtr_next_completed().
56321256Syl150051  * Transfer codes are enumerated in xgehal-fifo.h and xgehal-ring.h.
56331256Syl150051  *
56341256Syl150051  * Returns: one of the xge_hal_status_e{} enumerated types.
56351256Syl150051  * XGE_HAL_OK			- for success.
56361256Syl150051  * XGE_HAL_ERR_CRITICAL         - when encounters critical error.
56371256Syl150051  */
56381256Syl150051 xge_hal_status_e
xge_hal_device_handle_tcode(xge_hal_channel_h channelh,xge_hal_dtr_h dtrh,u8 t_code)56391256Syl150051 xge_hal_device_handle_tcode (xge_hal_channel_h channelh,
56401256Syl150051 			     xge_hal_dtr_h dtrh, u8 t_code)
56411256Syl150051 {
56421256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
56431256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
56441256Syl150051 
56451256Syl150051 	if (t_code > 15) {
56461256Syl150051 		xge_os_printf("invalid t_code %d", t_code);
56471256Syl150051 		return XGE_HAL_OK;
56481256Syl150051 	}
56491256Syl150051 
56501256Syl150051 	if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
56511256Syl150051 	        hldev->stats.sw_dev_err_stats.txd_t_code_err_cnt[t_code]++;
56521256Syl150051 
56531256Syl150051 #if defined(XGE_HAL_DEBUG_BAD_TCODE)
56541256Syl150051         xge_hal_fifo_txd_t *txdp = (xge_hal_fifo_txd_t *)dtrh;
56553115Syl150051         xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"
56563115Syl150051 		XGE_OS_LLXFMT":"XGE_OS_LLXFMT,
56573115Syl150051 		txdp->control_1, txdp->control_2, txdp->buffer_pointer,
56583115Syl150051 		txdp->host_control);
56591256Syl150051 #endif
56601256Syl150051 
56611256Syl150051 		/* handle link "down" immediately without going through
56621256Syl150051 		 * xge_hal_device_poll() routine. */
56631256Syl150051 		if (t_code == XGE_HAL_TXD_T_CODE_LOSS_OF_LINK) {
56641256Syl150051 			/* link is down */
56651256Syl150051 			if (hldev->link_state != XGE_HAL_LINK_DOWN) {
56661256Syl150051 				xge_hal_pci_bar0_t *bar0 =
56671256Syl150051 				(xge_hal_pci_bar0_t *)(void *)hldev->bar0;
56681256Syl150051 				u64 val64;
56691256Syl150051 
56701256Syl150051 				hldev->link_state = XGE_HAL_LINK_DOWN;
56711256Syl150051 
56721256Syl150051 				val64 = xge_os_pio_mem_read64(hldev->pdev,
56731256Syl150051 				    hldev->regh0, &bar0->adapter_control);
56741256Syl150051 
56751256Syl150051 				/* turn off LED */
56761256Syl150051 				val64 = val64 & (~XGE_HAL_ADAPTER_LED_ON);
56771256Syl150051 				xge_os_pio_mem_write64(hldev->pdev,
56781256Syl150051 						hldev->regh0, val64,
56791256Syl150051 						&bar0->adapter_control);
56801256Syl150051 
56811256Syl150051 				g_xge_hal_driver->uld_callbacks.link_down(
56821256Syl150051 						hldev->upper_layer_info);
56831256Syl150051 			}
56841256Syl150051 		} else if (t_code == XGE_HAL_TXD_T_CODE_ABORT_BUFFER ||
56851256Syl150051 		           t_code == XGE_HAL_TXD_T_CODE_ABORT_DTOR) {
56861256Syl150051                         __hal_device_handle_targetabort(hldev);
56871256Syl150051 			return XGE_HAL_ERR_CRITICAL;
56881256Syl150051 		}
56896937Sxw161283 		return XGE_HAL_ERR_PKT_DROP;
56901256Syl150051 	} else if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
56911256Syl150051 	        hldev->stats.sw_dev_err_stats.rxd_t_code_err_cnt[t_code]++;
56921256Syl150051 
56931256Syl150051 #if defined(XGE_HAL_DEBUG_BAD_TCODE)
56941256Syl150051 		xge_hal_ring_rxd_1_t *rxdp = (xge_hal_ring_rxd_1_t *)dtrh;
56953115Syl150051 		xge_os_printf(""XGE_OS_LLXFMT":"XGE_OS_LLXFMT":"XGE_OS_LLXFMT
56963115Syl150051 			":"XGE_OS_LLXFMT, rxdp->control_1,
56973115Syl150051 			rxdp->control_2, rxdp->buffer0_ptr,
56983115Syl150051 			rxdp->host_control);
56991256Syl150051 #endif
57001256Syl150051 		if (t_code == XGE_HAL_RXD_T_CODE_BAD_ECC) {
57011256Syl150051 			hldev->stats.sw_dev_err_stats.ecc_err_cnt++;
57021256Syl150051 			__hal_device_handle_eccerr(hldev, "rxd_t_code",
57031256Syl150051 						   (u64)t_code);
57041256Syl150051 			return XGE_HAL_ERR_CRITICAL;
57051256Syl150051 		} else if (t_code == XGE_HAL_RXD_T_CODE_PARITY ||
57061256Syl150051 			   t_code == XGE_HAL_RXD_T_CODE_PARITY_ABORT) {
57071256Syl150051 			hldev->stats.sw_dev_err_stats.parity_err_cnt++;
57081256Syl150051 			__hal_device_handle_parityerr(hldev, "rxd_t_code",
57091256Syl150051 						      (u64)t_code);
57101256Syl150051 			return XGE_HAL_ERR_CRITICAL;
57116937Sxw161283 		/* do not drop if detected unknown IPv6 extension */
57126937Sxw161283 		} else if (t_code != XGE_HAL_RXD_T_CODE_UNKNOWN_PROTO) {
57136937Sxw161283 			return XGE_HAL_ERR_PKT_DROP;
57141256Syl150051 		}
57151256Syl150051 	}
57161256Syl150051 	return XGE_HAL_OK;
57171256Syl150051 }
57181256Syl150051 
57191256Syl150051 /**
57201256Syl150051  * xge_hal_device_link_state - Get link state.
57211256Syl150051  * @devh: HAL device handle.
57221256Syl150051  * @ls: Link state, see xge_hal_device_link_state_e{}.
57231256Syl150051  *
57241256Syl150051  * Get link state.
57251256Syl150051  * Returns: XGE_HAL_OK.
57261256Syl150051  * See also: xge_hal_device_link_state_e{}.
57271256Syl150051  */
xge_hal_device_link_state(xge_hal_device_h devh,xge_hal_device_link_state_e * ls)57281256Syl150051 xge_hal_status_e xge_hal_device_link_state(xge_hal_device_h devh,
57291256Syl150051 			xge_hal_device_link_state_e *ls)
57301256Syl150051 {
57311256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
57321256Syl150051 
57331256Syl150051 	xge_assert(ls != NULL);
57341256Syl150051 	*ls = hldev->link_state;
57351256Syl150051 	return XGE_HAL_OK;
57361256Syl150051 }
57371256Syl150051 
57381256Syl150051 /**
57391256Syl150051  * xge_hal_device_sched_timer - Configure scheduled device interrupt.
57401256Syl150051  * @devh: HAL device handle.
57411256Syl150051  * @interval_us: Time interval, in miscoseconds.
57421256Syl150051  *            Unlike transmit and receive interrupts,
57431256Syl150051  *            the scheduled interrupt is generated independently of
57441256Syl150051  *            traffic, but purely based on time.
57451256Syl150051  * @one_shot: 1 - generate scheduled interrupt only once.
57461256Syl150051  *            0 - generate scheduled interrupt periodically at the specified
57471256Syl150051  *            @interval_us interval.
57481256Syl150051  *
57491256Syl150051  * (Re-)configure scheduled interrupt. Can be called at runtime to change
57501256Syl150051  * the setting, generate one-shot interrupts based on the resource and/or
57511256Syl150051  * traffic conditions, other purposes.
57521256Syl150051  * See also: xge_hal_device_config_t{}.
57531256Syl150051  */
xge_hal_device_sched_timer(xge_hal_device_h devh,int interval_us,int one_shot)57541256Syl150051 void xge_hal_device_sched_timer(xge_hal_device_h devh, int interval_us,
57551256Syl150051 			int one_shot)
57561256Syl150051 {
57571256Syl150051 	u64 val64;
57581256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
57591256Syl150051 	xge_hal_pci_bar0_t *bar0 =
57601256Syl150051 		(xge_hal_pci_bar0_t *)(void *)hldev->bar0;
57611256Syl150051 	unsigned int interval = hldev->config.pci_freq_mherz * interval_us;
57621256Syl150051 
57631256Syl150051 	interval = __hal_fix_time_ival_herc(hldev, interval);
57641256Syl150051 
57651256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
57661256Syl150051 				    &bar0->scheduled_int_ctrl);
57671256Syl150051 	if (interval) {
57681256Syl150051 		val64 &= XGE_HAL_SCHED_INT_PERIOD_MASK;
57691256Syl150051 		val64 |= XGE_HAL_SCHED_INT_PERIOD(interval);
57701256Syl150051 		if (one_shot) {
57711256Syl150051 			val64 |= XGE_HAL_SCHED_INT_CTRL_ONE_SHOT;
57721256Syl150051 		}
57731256Syl150051 		val64 |= XGE_HAL_SCHED_INT_CTRL_TIMER_EN;
57741256Syl150051 	} else {
57751256Syl150051 		val64 &= ~XGE_HAL_SCHED_INT_CTRL_TIMER_EN;
57761256Syl150051 	}
57771256Syl150051 
57781256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
57791256Syl150051 			     val64, &bar0->scheduled_int_ctrl);
57801256Syl150051 
57813115Syl150051 	xge_debug_device(XGE_TRACE, "sched_timer 0x"XGE_OS_LLXFMT": %s",
57821256Syl150051 			  (unsigned long long)val64,
57831256Syl150051 			  interval ? "enabled" : "disabled");
57841256Syl150051 }
57851256Syl150051 
57861256Syl150051 /**
57871256Syl150051  * xge_hal_device_check_id - Verify device ID.
57881256Syl150051  * @devh: HAL device handle.
57891256Syl150051  *
57901256Syl150051  * Verify device ID.
57911256Syl150051  * Returns: one of the xge_hal_card_e{} enumerated types.
57921256Syl150051  * See also: xge_hal_card_e{}.
57931256Syl150051  */
57941256Syl150051 xge_hal_card_e
xge_hal_device_check_id(xge_hal_device_h devh)57951256Syl150051 xge_hal_device_check_id(xge_hal_device_h devh)
57961256Syl150051 {
57971256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
57981256Syl150051 	switch (hldev->device_id) {
57991256Syl150051 	case XGE_PCI_DEVICE_ID_XENA_1:
58001256Syl150051 	case XGE_PCI_DEVICE_ID_XENA_2:
58011256Syl150051 		return XGE_HAL_CARD_XENA;
58021256Syl150051 	case XGE_PCI_DEVICE_ID_HERC_1:
58031256Syl150051 	case XGE_PCI_DEVICE_ID_HERC_2:
58041256Syl150051 		return XGE_HAL_CARD_HERC;
58056937Sxw161283 	case XGE_PCI_DEVICE_ID_TITAN_1:
58066937Sxw161283 	case XGE_PCI_DEVICE_ID_TITAN_2:
58076937Sxw161283 		return XGE_HAL_CARD_TITAN;
58081256Syl150051 	default:
58091256Syl150051 		return XGE_HAL_CARD_UNKNOWN;
58101256Syl150051 	}
58111256Syl150051 }
58121256Syl150051 
58131256Syl150051 /**
58141256Syl150051  * xge_hal_device_pci_info_get - Get PCI bus informations such as width,
58151256Syl150051  *			 frequency, and mode from previously stored values.
58161256Syl150051  * @devh:		HAL device handle.
58171256Syl150051  * @pci_mode:		pointer to a variable of enumerated type
58181256Syl150051  *			xge_hal_pci_mode_e{}.
58191256Syl150051  * @bus_frequency:	pointer to a variable of enumerated type
58201256Syl150051  *			xge_hal_pci_bus_frequency_e{}.
58211256Syl150051  * @bus_width:		pointer to a variable of enumerated type
58221256Syl150051  *			xge_hal_pci_bus_width_e{}.
58231256Syl150051  *
58241256Syl150051  * Get pci mode, frequency, and PCI bus width.
58251256Syl150051  * Returns: one of the xge_hal_status_e{} enumerated types.
58261256Syl150051  * XGE_HAL_OK			- for success.
58271256Syl150051  * XGE_HAL_ERR_INVALID_DEVICE	- for invalid device handle.
58281256Syl150051  * See Also: xge_hal_pci_mode_e, xge_hal_pci_mode_e, xge_hal_pci_width_e.
58291256Syl150051  */
58301256Syl150051 xge_hal_status_e
xge_hal_device_pci_info_get(xge_hal_device_h devh,xge_hal_pci_mode_e * pci_mode,xge_hal_pci_bus_frequency_e * bus_frequency,xge_hal_pci_bus_width_e * bus_width)58311256Syl150051 xge_hal_device_pci_info_get(xge_hal_device_h devh, xge_hal_pci_mode_e *pci_mode,
58321256Syl150051 		xge_hal_pci_bus_frequency_e *bus_frequency,
58331256Syl150051 		xge_hal_pci_bus_width_e *bus_width)
58341256Syl150051 {
58351256Syl150051 	xge_hal_status_e rc_status;
58361256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
58371256Syl150051 
58381256Syl150051 	if (!hldev || !hldev->is_initialized || hldev->magic != XGE_HAL_MAGIC) {
58391256Syl150051 		rc_status =  XGE_HAL_ERR_INVALID_DEVICE;
58401256Syl150051 		xge_debug_device(XGE_ERR,
58411256Syl150051 		        "xge_hal_device_pci_info_get error, rc %d for device %p",
58421256Syl150051 			rc_status, hldev);
58431256Syl150051 
58441256Syl150051 		return rc_status;
58451256Syl150051 	}
58461256Syl150051 
58471256Syl150051 	*pci_mode	= hldev->pci_mode;
58481256Syl150051 	*bus_frequency	= hldev->bus_frequency;
58491256Syl150051 	*bus_width	= hldev->bus_width;
58501256Syl150051 	rc_status	= XGE_HAL_OK;
58511256Syl150051 	return rc_status;
58521256Syl150051 }
58531256Syl150051 
58541256Syl150051 /**
58551256Syl150051  * xge_hal_reinitialize_hw
58561256Syl150051  * @hldev: private member of the device structure.
58571256Syl150051  *
58581256Syl150051  * This function will soft reset the NIC and re-initalize all the
58591256Syl150051  * I/O registers to the values they had after it's inital initialization
58601256Syl150051  * through the probe function.
58611256Syl150051  */
xge_hal_reinitialize_hw(xge_hal_device_t * hldev)58621256Syl150051 int xge_hal_reinitialize_hw(xge_hal_device_t * hldev)
58631256Syl150051 {
58641256Syl150051 	(void) xge_hal_device_reset(hldev);
58651256Syl150051 	if (__hal_device_hw_initialize(hldev) != XGE_HAL_OK) {
58661256Syl150051 		xge_hal_device_terminate(hldev);
58671256Syl150051 		(void) __hal_device_reset(hldev);
58681256Syl150051 		return 1;
58691256Syl150051 	}
58701256Syl150051 	return 0;
58711256Syl150051 }
58721256Syl150051 
58731256Syl150051 
58741256Syl150051 /*
58751256Syl150051  * __hal_read_spdm_entry_line
58761256Syl150051  * @hldev: pointer to xge_hal_device_t structure
58771256Syl150051  * @spdm_line: spdm line in the spdm entry to be read.
58781256Syl150051  * @spdm_entry: spdm entry of the spdm_line in the SPDM table.
58791256Syl150051  * @spdm_line_val: Contains the value stored in the spdm line.
58801256Syl150051  *
58811256Syl150051  * SPDM table contains upto a maximum of 256 spdm entries.
58821256Syl150051  * Each spdm entry contains 8 lines and each line stores 8 bytes.
58831256Syl150051  * This function reads the spdm line(addressed by @spdm_line)
58841256Syl150051  * of the spdm entry(addressed by @spdm_entry) in
58851256Syl150051  * the SPDM table.
58861256Syl150051  */
58871256Syl150051 xge_hal_status_e
__hal_read_spdm_entry_line(xge_hal_device_t * hldev,u8 spdm_line,u16 spdm_entry,u64 * spdm_line_val)58881256Syl150051 __hal_read_spdm_entry_line(xge_hal_device_t *hldev, u8 spdm_line,
58891256Syl150051 			u16 spdm_entry, u64 *spdm_line_val)
58901256Syl150051 {
58911256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
58921256Syl150051 	u64 val64;
58931256Syl150051 
58941256Syl150051 	val64 = XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE |
58951256Syl150051 		XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_LINE_SEL(spdm_line) |
58961256Syl150051 		XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_OFFSET(spdm_entry);
58971256Syl150051 
58981256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
58991256Syl150051 			&bar0->rts_rth_spdm_mem_ctrl);
59001256Syl150051 
59011256Syl150051 	/* poll until done */
59021256Syl150051 	if (__hal_device_register_poll(hldev,
59031256Syl150051 		&bar0->rts_rth_spdm_mem_ctrl, 0,
59041256Syl150051 		XGE_HAL_RTS_RTH_SPDM_MEM_CTRL_STROBE,
59051256Syl150051 		XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
59061256Syl150051 
59071256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
59081256Syl150051 	}
59091256Syl150051 
59101256Syl150051 	*spdm_line_val = xge_os_pio_mem_read64(hldev->pdev,
59111256Syl150051 				hldev->regh0, &bar0->rts_rth_spdm_mem_data);
59121256Syl150051 	return XGE_HAL_OK;
59131256Syl150051 }
59141256Syl150051 
59151256Syl150051 
59161256Syl150051 /*
59171256Syl150051  * __hal_get_free_spdm_entry
59181256Syl150051  * @hldev: pointer to xge_hal_device_t structure
59191256Syl150051  * @spdm_entry: Contains an index to the unused spdm entry in the SPDM table.
59201256Syl150051  *
59211256Syl150051  * This function returns an index of unused spdm entry in the SPDM
59221256Syl150051  * table.
59231256Syl150051  */
59241256Syl150051 static xge_hal_status_e
__hal_get_free_spdm_entry(xge_hal_device_t * hldev,u16 * spdm_entry)59251256Syl150051 __hal_get_free_spdm_entry(xge_hal_device_t *hldev, u16 *spdm_entry)
59261256Syl150051 {
59271256Syl150051 	xge_hal_status_e status;
59281256Syl150051 	u64 spdm_line_val=0;
59291256Syl150051 
59301256Syl150051 	/*
59311256Syl150051 	 * Search in the local SPDM table for a free slot.
59321256Syl150051 	 */
59331256Syl150051 	*spdm_entry = 0;
59341256Syl150051 	for(; *spdm_entry < hldev->spdm_max_entries; (*spdm_entry)++) {
59351256Syl150051 		if (hldev->spdm_table[*spdm_entry]->in_use) {
59361256Syl150051 			break;
59371256Syl150051 		}
59381256Syl150051 	}
59391256Syl150051 
59401256Syl150051 	if (*spdm_entry >= hldev->spdm_max_entries) {
59411256Syl150051 		return XGE_HAL_ERR_SPDM_TABLE_FULL;
59421256Syl150051 	}
59431256Syl150051 
59441256Syl150051 	/*
59451256Syl150051 	 * Make sure that the corresponding spdm entry in the SPDM
59461256Syl150051 	 * table is free.
59471256Syl150051 	 * Seventh line of the spdm entry contains information about
59481256Syl150051 	 * whether the entry is free or not.
59491256Syl150051 	 */
59501256Syl150051 	if ((status = __hal_read_spdm_entry_line(hldev, 7, *spdm_entry,
59511256Syl150051 					&spdm_line_val)) != XGE_HAL_OK) {
59521256Syl150051 		return status;
59531256Syl150051 	}
59541256Syl150051 
59551256Syl150051 	/* BIT(63) in spdm_line 7 corresponds to entry_enable bit */
59561256Syl150051 	if ((spdm_line_val & BIT(63))) {
59571256Syl150051 		/*
59581256Syl150051 		 * Log a warning
59591256Syl150051 		 */
59601256Syl150051 		xge_debug_device(XGE_ERR, "Local SPDM table is not "
59611256Syl150051 			  "consistent with the actual one for the spdm "
59626937Sxw161283 			  "entry %d", *spdm_entry);
59631256Syl150051 		return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT;
59641256Syl150051 	}
59651256Syl150051 
59661256Syl150051 	return XGE_HAL_OK;
59671256Syl150051 }
59681256Syl150051 
59691256Syl150051 
59706937Sxw161283 /*
59716937Sxw161283  * __hal_calc_jhash - Calculate Jenkins hash.
59726937Sxw161283  * @msg: Jenkins hash algorithm key.
59736937Sxw161283  * @length: Length of the key.
59746937Sxw161283  * @golden_ratio: Jenkins hash golden ratio.
59756937Sxw161283  * @init_value: Jenkins hash initial value.
59766937Sxw161283  *
59776937Sxw161283  * This function implements the Jenkins based algorithm used for the
59786937Sxw161283  * calculation of the RTH hash.
59796937Sxw161283  * Returns:  Jenkins hash value.
59806937Sxw161283  *
59816937Sxw161283  */
59826937Sxw161283 static u32
__hal_calc_jhash(u8 * msg,u32 length,u32 golden_ratio,u32 init_value)59836937Sxw161283 __hal_calc_jhash(u8 *msg, u32 length, u32 golden_ratio, u32 init_value)
59846937Sxw161283 {
59856937Sxw161283 
59866937Sxw161283 	register u32 a,b,c,len;
59876937Sxw161283 
59886937Sxw161283 	/*
59896937Sxw161283 	 * Set up the internal state
59906937Sxw161283 	 */
59916937Sxw161283 	len = length;
59926937Sxw161283 	a = b = golden_ratio;  /* the golden ratio; an arbitrary value */
59936937Sxw161283 	c = init_value;         /* the previous hash value */
59946937Sxw161283 
59956937Sxw161283 	/*  handle most of the key */
59966937Sxw161283 	while (len >= 12)
59976937Sxw161283 	{
59986937Sxw161283 		a += (msg[0] + ((u32)msg[1]<<8) + ((u32)msg[2]<<16)
59996937Sxw161283 						 + ((u32)msg[3]<<24));
60006937Sxw161283 		b += (msg[4] + ((u32)msg[5]<<8) + ((u32)msg[6]<<16)
60016937Sxw161283 						 + ((u32)msg[7]<<24));
60026937Sxw161283 		c += (msg[8] + ((u32)msg[9]<<8) + ((u32)msg[10]<<16)
60036937Sxw161283 						 + ((u32)msg[11]<<24));
60046937Sxw161283 		mix(a,b,c);
60056937Sxw161283 		msg += 12; len -= 12;
60066937Sxw161283 	}
60076937Sxw161283 
60086937Sxw161283 	/*  handle the last 11 bytes */
60096937Sxw161283 	c += length;
60106937Sxw161283 	switch(len)  /* all the case statements fall through */
60116937Sxw161283 	{
60126937Sxw161283 		case 11: c+= ((u32)msg[10]<<24);
60136937Sxw161283 			 break;
60146937Sxw161283 		case 10: c+= ((u32)msg[9]<<16);
60156937Sxw161283 			 break;
60166937Sxw161283 		case 9 : c+= ((u32)msg[8]<<8);
60176937Sxw161283 			 break;
60186937Sxw161283 		/* the first byte of c is reserved for the length */
60196937Sxw161283 		case 8 : b+= ((u32)msg[7]<<24);
60206937Sxw161283 			 break;
60216937Sxw161283 		case 7 : b+= ((u32)msg[6]<<16);
60226937Sxw161283 			 break;
60236937Sxw161283 		case 6 : b+= ((u32)msg[5]<<8);
60246937Sxw161283 			 break;
60256937Sxw161283 		case 5 : b+= msg[4];
60266937Sxw161283 			 break;
60276937Sxw161283 		case 4 : a+= ((u32)msg[3]<<24);
60286937Sxw161283 			 break;
60296937Sxw161283 		case 3 : a+= ((u32)msg[2]<<16);
60306937Sxw161283 			 break;
60316937Sxw161283 		case 2 : a+= ((u32)msg[1]<<8);
60326937Sxw161283 			 break;
60336937Sxw161283 		case 1 : a+= msg[0];
60346937Sxw161283 			 break;
60356937Sxw161283 		/* case 0: nothing left to add */
60366937Sxw161283 	}
60376937Sxw161283 
60386937Sxw161283 	mix(a,b,c);
60396937Sxw161283 
60406937Sxw161283 	/* report the result */
60416937Sxw161283 	return c;
60426937Sxw161283 }
60436937Sxw161283 
60441256Syl150051 
60451256Syl150051 /**
60461256Syl150051  * xge_hal_spdm_entry_add - Add a new entry to the SPDM table.
60471256Syl150051  * @devh: HAL device handle.
60481256Syl150051  * @src_ip: Source ip address(IPv4/IPv6).
60491256Syl150051  * @dst_ip: Destination ip address(IPv4/IPv6).
60501256Syl150051  * @l4_sp: L4 source port.
60511256Syl150051  * @l4_dp: L4 destination port.
60521256Syl150051  * @is_tcp: Set to 1, if the protocol is TCP.
60531256Syl150051  *		   0, if the protocol is UDP.
60541256Syl150051  * @is_ipv4: Set to 1, if the protocol is IPv4.
60551256Syl150051  *		   0, if the protocol is IPv6.
60561256Syl150051  * @tgt_queue: Target queue to route the receive packet.
60571256Syl150051  *
60581256Syl150051  * This function add a new entry to the SPDM table.
60591256Syl150051  *
60601256Syl150051  * Returns:  XGE_HAL_OK - success.
60611256Syl150051  * XGE_HAL_ERR_SPDM_NOT_ENABLED -  SPDM support is not enabled.
60621256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to add a new entry with in
60631256Syl150051  *					the time(timeout).
60641256Syl150051  * XGE_HAL_ERR_SPDM_TABLE_FULL - SPDM table is full.
60651256Syl150051  * XGE_HAL_ERR_SPDM_INVALID_ENTRY - Invalid SPDM entry.
60661256Syl150051  *
60671256Syl150051  * See also: xge_hal_spdm_entry_remove{}.
60681256Syl150051  */
60691256Syl150051 xge_hal_status_e
xge_hal_spdm_entry_add(xge_hal_device_h devh,xge_hal_ipaddr_t * src_ip,xge_hal_ipaddr_t * dst_ip,u16 l4_sp,u16 l4_dp,u8 is_tcp,u8 is_ipv4,u8 tgt_queue)60701256Syl150051 xge_hal_spdm_entry_add(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip,
60711256Syl150051 		xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp,
60721256Syl150051 		u8 is_tcp, u8 is_ipv4, u8 tgt_queue)
60731256Syl150051 {
60741256Syl150051 
60751256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
60761256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
60771256Syl150051 	u32 jhash_value;
60781256Syl150051 	u32 jhash_init_val;
60791256Syl150051 	u32 jhash_golden_ratio;
60801256Syl150051 	u64 val64;
60811256Syl150051 	int off;
60821256Syl150051 	u16 spdm_entry;
60831256Syl150051 	u8  msg[XGE_HAL_JHASH_MSG_LEN];
60841256Syl150051 	int ipaddr_len;
60851256Syl150051 	xge_hal_status_e status;
60861256Syl150051 
60871256Syl150051 
60881256Syl150051 	if (!hldev->config.rth_spdm_en) {
60891256Syl150051 		return XGE_HAL_ERR_SPDM_NOT_ENABLED;
60901256Syl150051 	}
60911256Syl150051 
60921256Syl150051 	if ((tgt_queue <  XGE_HAL_MIN_RING_NUM) ||
60931256Syl150051 		(tgt_queue  >  XGE_HAL_MAX_RING_NUM)) {
60941256Syl150051 		return XGE_HAL_ERR_SPDM_INVALID_ENTRY;
60951256Syl150051 	}
60961256Syl150051 
60971256Syl150051 
60981256Syl150051 	/*
60991256Syl150051 	 * Calculate the jenkins hash.
61001256Syl150051 	 */
61011256Syl150051 	/*
61021256Syl150051 	 * Create the Jenkins hash algorithm key.
61031256Syl150051 	 * key = {L3SA, L3DA, L4SP, L4DP}, if SPDM is configured to
61041256Syl150051 	 * use L4 information. Otherwize key = {L3SA, L3DA}.
61051256Syl150051 	 */
61061256Syl150051 
61071256Syl150051 	if (is_ipv4) {
61081256Syl150051 		ipaddr_len = 4;   // In bytes
61091256Syl150051 	} else {
61101256Syl150051 		ipaddr_len = 16;
61111256Syl150051 	}
61121256Syl150051 
61131256Syl150051 	/*
61141256Syl150051 	 * Jenkins hash algorithm expects the key in the big endian
61151256Syl150051 	 * format. Since key is the byte array, memcpy won't work in the
61161256Syl150051 	 * case of little endian. So, the current code extracts each
61171256Syl150051 	 * byte starting from MSB and store it in the key.
61181256Syl150051 	 */
61191256Syl150051 	if (is_ipv4) {
61201256Syl150051 		for (off = 0; off < ipaddr_len; off++) {
61211256Syl150051 			u32 mask = vBIT32(0xff,(off*8),8);
61221256Syl150051 			int shift = 32-(off+1)*8;
61231256Syl150051 			msg[off] = (u8)((src_ip->ipv4.addr & mask) >> shift);
61241256Syl150051 			msg[off+ipaddr_len] =
61251256Syl150051 				(u8)((dst_ip->ipv4.addr & mask) >> shift);
61261256Syl150051 		}
61271256Syl150051 	} else {
61281256Syl150051 		for (off = 0; off < ipaddr_len; off++) {
61291256Syl150051 			int loc = off % 8;
61301256Syl150051 			u64 mask = vBIT(0xff,(loc*8),8);
61311256Syl150051 			int shift = 64-(loc+1)*8;
61321256Syl150051 
61331256Syl150051 			msg[off] = (u8)((src_ip->ipv6.addr[off/8] & mask)
61341256Syl150051 						>> shift);
61351256Syl150051 			msg[off+ipaddr_len] = (u8)((dst_ip->ipv6.addr[off/8]
61361256Syl150051 						    & mask) >> shift);
61371256Syl150051 		}
61381256Syl150051 	}
61391256Syl150051 
61401256Syl150051 	off = (2*ipaddr_len);
61411256Syl150051 
61421256Syl150051 	if (hldev->config.rth_spdm_use_l4) {
61431256Syl150051 		msg[off] = (u8)((l4_sp & 0xff00) >> 8);
61441256Syl150051 		msg[off + 1] = (u8)(l4_sp & 0xff);
61451256Syl150051 		msg[off + 2] = (u8)((l4_dp & 0xff00) >> 8);
61461256Syl150051 		msg[off + 3] = (u8)(l4_dp & 0xff);
61471256Syl150051 		off += 4;
61481256Syl150051 	}
61491256Syl150051 
61501256Syl150051 	/*
61511256Syl150051 	 * Calculate jenkins hash for this configuration
61521256Syl150051 	 */
61531256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev,
61541256Syl150051 				    hldev->regh0,
61551256Syl150051 				    &bar0->rts_rth_jhash_cfg);
61561256Syl150051 	jhash_golden_ratio = (u32)(val64 >> 32);
61571256Syl150051 	jhash_init_val = (u32)(val64 & 0xffffffff);
61581256Syl150051 
61591256Syl150051 	jhash_value = __hal_calc_jhash(msg, off,
61601256Syl150051 				       jhash_golden_ratio,
61611256Syl150051 				       jhash_init_val);
61621256Syl150051 
61631256Syl150051 	xge_os_spin_lock(&hldev->spdm_lock);
61641256Syl150051 
61651256Syl150051 	/*
61661256Syl150051 	 * Locate a free slot in the SPDM table. To avoid a seach in the
61671256Syl150051 	 * actual SPDM table, which is very expensive in terms of time,
61681256Syl150051 	 * we are maintaining a local copy of  the table and the search for
61691256Syl150051 	 * the free entry is performed in the local table.
61701256Syl150051 	 */
61711256Syl150051 	if ((status = __hal_get_free_spdm_entry(hldev,&spdm_entry))
61721256Syl150051 			!= XGE_HAL_OK) {
61731256Syl150051 		xge_os_spin_unlock(&hldev->spdm_lock);
61741256Syl150051 		return status;
61751256Syl150051 	}
61761256Syl150051 
61771256Syl150051 	/*
61781256Syl150051 	 * Add this entry to the SPDM table
61791256Syl150051 	 */
61801256Syl150051 	status =  __hal_spdm_entry_add(hldev, src_ip, dst_ip, l4_sp, l4_dp,
61811256Syl150051 				     is_tcp, is_ipv4, tgt_queue,
61821256Syl150051 				     jhash_value, /* calculated jhash */
61831256Syl150051 				     spdm_entry);
61841256Syl150051 
61851256Syl150051 	xge_os_spin_unlock(&hldev->spdm_lock);
61861256Syl150051 
61871256Syl150051 	return status;
61881256Syl150051 }
61891256Syl150051 
61901256Syl150051 /**
61911256Syl150051  * xge_hal_spdm_entry_remove - Remove an entry from the SPDM table.
61921256Syl150051  * @devh: HAL device handle.
61931256Syl150051  * @src_ip: Source ip address(IPv4/IPv6).
61941256Syl150051  * @dst_ip: Destination ip address(IPv4/IPv6).
61951256Syl150051  * @l4_sp: L4 source port.
61961256Syl150051  * @l4_dp: L4 destination port.
61971256Syl150051  * @is_tcp: Set to 1, if the protocol is TCP.
61981256Syl150051  *		   0, if the protocol os UDP.
61991256Syl150051  * @is_ipv4: Set to 1, if the protocol is IPv4.
62001256Syl150051  *		   0, if the protocol is IPv6.
62011256Syl150051  *
62021256Syl150051  * This function remove an entry from the SPDM table.
62031256Syl150051  *
62041256Syl150051  * Returns:  XGE_HAL_OK - success.
62051256Syl150051  * XGE_HAL_ERR_SPDM_NOT_ENABLED -  SPDM support is not enabled.
62061256Syl150051  * XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING - Failed to remove an entry with in
62071256Syl150051  *					the time(timeout).
62081256Syl150051  * XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND - Unable to locate the entry in the SPDM
62091256Syl150051  *					table.
62101256Syl150051  *
62111256Syl150051  * See also: xge_hal_spdm_entry_add{}.
62121256Syl150051  */
62131256Syl150051 xge_hal_status_e
xge_hal_spdm_entry_remove(xge_hal_device_h devh,xge_hal_ipaddr_t * src_ip,xge_hal_ipaddr_t * dst_ip,u16 l4_sp,u16 l4_dp,u8 is_tcp,u8 is_ipv4)62141256Syl150051 xge_hal_spdm_entry_remove(xge_hal_device_h devh, xge_hal_ipaddr_t *src_ip,
62151256Syl150051 		xge_hal_ipaddr_t *dst_ip, u16 l4_sp, u16 l4_dp,
62161256Syl150051 		u8 is_tcp, u8 is_ipv4)
62171256Syl150051 {
62181256Syl150051 
62191256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
62201256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
62211256Syl150051 	u64 val64;
62221256Syl150051 	u16 spdm_entry;
62231256Syl150051 	xge_hal_status_e status;
62241256Syl150051 	u64 spdm_line_arr[8];
62251256Syl150051 	u8 line_no;
62261256Syl150051 	u8 spdm_is_tcp;
62271256Syl150051 	u8 spdm_is_ipv4;
62281256Syl150051 	u16 spdm_l4_sp;
62291256Syl150051 	u16 spdm_l4_dp;
62301256Syl150051 
62311256Syl150051 	if (!hldev->config.rth_spdm_en) {
62321256Syl150051 		return XGE_HAL_ERR_SPDM_NOT_ENABLED;
62331256Syl150051 	}
62341256Syl150051 
62351256Syl150051 	xge_os_spin_lock(&hldev->spdm_lock);
62361256Syl150051 
62371256Syl150051 	/*
62381256Syl150051 	 * Poll the rxpic_int_reg register until spdm ready bit is set or
62391256Syl150051 	 * timeout happens.
62401256Syl150051 	 */
62411256Syl150051 	if (__hal_device_register_poll(hldev, &bar0->rxpic_int_reg, 1,
62421256Syl150051 			XGE_HAL_RX_PIC_INT_REG_SPDM_READY,
62431256Syl150051 			XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
62441256Syl150051 
62451256Syl150051 		/* upper layer may require to repeat */
62461256Syl150051 		xge_os_spin_unlock(&hldev->spdm_lock);
62471256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
62481256Syl150051 	}
62491256Syl150051 
62501256Syl150051 	/*
62511256Syl150051 	 * Clear the SPDM READY bit.
62521256Syl150051 	 */
62531256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
62541256Syl150051                                &bar0->rxpic_int_reg);
62551256Syl150051 	val64 &= ~XGE_HAL_RX_PIC_INT_REG_SPDM_READY;
62561256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
62571256Syl150051                       &bar0->rxpic_int_reg);
62581256Syl150051 
62591256Syl150051 	/*
62601256Syl150051 	 * Search in the local SPDM table to get the index of the
62611256Syl150051 	 * corresponding entry in the SPDM table.
62621256Syl150051 	 */
62631256Syl150051 	spdm_entry = 0;
62641256Syl150051 	for (;spdm_entry < hldev->spdm_max_entries; spdm_entry++) {
62651256Syl150051 		if ((!hldev->spdm_table[spdm_entry]->in_use) ||
62661256Syl150051 		    (hldev->spdm_table[spdm_entry]->is_tcp != is_tcp) ||
62671256Syl150051 		    (hldev->spdm_table[spdm_entry]->l4_sp != l4_sp) ||
62681256Syl150051 		    (hldev->spdm_table[spdm_entry]->l4_dp != l4_dp) ||
62691256Syl150051 		    (hldev->spdm_table[spdm_entry]->is_ipv4 != is_ipv4)) {
62701256Syl150051 			continue;
62711256Syl150051 		}
62721256Syl150051 
62731256Syl150051 		/*
62741256Syl150051 		 * Compare the src/dst IP addresses of source and target
62751256Syl150051 		 */
62761256Syl150051 		if (is_ipv4) {
62771256Syl150051 			if ((hldev->spdm_table[spdm_entry]->src_ip.ipv4.addr
62781256Syl150051 			     != src_ip->ipv4.addr) ||
62791256Syl150051 			    (hldev->spdm_table[spdm_entry]->dst_ip.ipv4.addr
62801256Syl150051 			     != dst_ip->ipv4.addr)) {
62811256Syl150051 				continue;
62821256Syl150051 			}
62831256Syl150051 		} else {
62841256Syl150051 			if ((hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[0]
62851256Syl150051 			     != src_ip->ipv6.addr[0]) ||
62861256Syl150051 			    (hldev->spdm_table[spdm_entry]->src_ip.ipv6.addr[1]
62871256Syl150051 			     != src_ip->ipv6.addr[1]) ||
62881256Syl150051 			    (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[0]
62891256Syl150051 			     != dst_ip->ipv6.addr[0]) ||
62901256Syl150051 			    (hldev->spdm_table[spdm_entry]->dst_ip.ipv6.addr[1]
62911256Syl150051 			     != dst_ip->ipv6.addr[1])) {
62921256Syl150051 				continue;
62931256Syl150051 			}
62941256Syl150051 		}
62951256Syl150051 		break;
62961256Syl150051 	}
62971256Syl150051 
62981256Syl150051 	if (spdm_entry >= hldev->spdm_max_entries) {
62991256Syl150051 		xge_os_spin_unlock(&hldev->spdm_lock);
63001256Syl150051 		return XGE_HAL_ERR_SPDM_ENTRY_NOT_FOUND;
63011256Syl150051 	}
63021256Syl150051 
63031256Syl150051 	/*
63041256Syl150051 	 * Retrieve the corresponding entry from the SPDM table and
63051256Syl150051 	 * make sure that the data is consistent.
63061256Syl150051 	 */
63071256Syl150051 	for(line_no = 0; line_no < 8; line_no++) {
63081256Syl150051 
63091256Syl150051 		/*
63101256Syl150051 		 *  SPDM line 2,3,4 are valid only for IPv6 entry.
63111256Syl150051 		 *  SPDM line 5 & 6 are reserved. We don't have to
63121256Syl150051 		 *  read these entries in the above cases.
63131256Syl150051 		 */
63141256Syl150051 		if (((is_ipv4) &&
63151256Syl150051 			((line_no == 2)||(line_no == 3)||(line_no == 4))) ||
63161256Syl150051 		     (line_no == 5) ||
63171256Syl150051 		     (line_no == 6)) {
63181256Syl150051 			continue;
63191256Syl150051 		}
63201256Syl150051 
63211256Syl150051 		if ((status = __hal_read_spdm_entry_line(
63221256Syl150051 					hldev,
63231256Syl150051 					line_no,
63241256Syl150051 					spdm_entry,
63251256Syl150051 					&spdm_line_arr[line_no]))
63261256Syl150051 							!= XGE_HAL_OK) {
63271256Syl150051 			xge_os_spin_unlock(&hldev->spdm_lock);
63281256Syl150051 			return status;
63291256Syl150051 		}
63301256Syl150051 	}
63311256Syl150051 
63321256Syl150051 	/*
63331256Syl150051 	 * Seventh line of the spdm entry contains the entry_enable
63341256Syl150051 	 * bit. Make sure that the entry_enable bit of this spdm entry
63351256Syl150051 	 * is set.
63361256Syl150051 	 * To remove an entry from the SPDM table, reset this
63371256Syl150051 	 * bit.
63381256Syl150051 	 */
63391256Syl150051 	if (!(spdm_line_arr[7] & BIT(63))) {
63401256Syl150051 		/*
63411256Syl150051 		 * Log a warning
63421256Syl150051 		 */
63431256Syl150051 		xge_debug_device(XGE_ERR, "Local SPDM table is not "
63441256Syl150051 			"consistent with the actual one for the spdm "
63456937Sxw161283 			"entry %d ", spdm_entry);
63461256Syl150051 		goto err_exit;
63471256Syl150051 	}
63481256Syl150051 
63491256Syl150051 	/*
63501256Syl150051 	 *  Retreive the L4 SP/DP, src/dst ip addresses from the SPDM
63511256Syl150051 	 *  table and do a comparision.
63521256Syl150051 	 */
63531256Syl150051 	spdm_is_tcp = (u8)((spdm_line_arr[0] & BIT(59)) >> 4);
63541256Syl150051 	spdm_is_ipv4 = (u8)(spdm_line_arr[0] & BIT(63));
63551256Syl150051 	spdm_l4_sp = (u16)(spdm_line_arr[0] >> 48);
63561256Syl150051 	spdm_l4_dp = (u16)((spdm_line_arr[0] >> 32) & 0xffff);
63571256Syl150051 
63581256Syl150051 
63591256Syl150051 	if ((spdm_is_tcp != is_tcp) ||
63601256Syl150051 	    (spdm_is_ipv4 != is_ipv4) ||
63611256Syl150051 	    (spdm_l4_sp != l4_sp) ||
63621256Syl150051 	    (spdm_l4_dp != l4_dp)) {
63631256Syl150051 		/*
63641256Syl150051 		 * Log a warning
63651256Syl150051 		 */
63661256Syl150051 		xge_debug_device(XGE_ERR, "Local SPDM table is not "
63671256Syl150051 			"consistent with the actual one for the spdm "
63686937Sxw161283 			"entry %d ", spdm_entry);
63691256Syl150051 		goto err_exit;
63701256Syl150051 	}
63711256Syl150051 
63721256Syl150051 	if (is_ipv4) {
63731256Syl150051 		/* Upper 32 bits of spdm_line(64 bit) contains the
63741256Syl150051 		 * src IPv4 address. Lower 32 bits of spdm_line
63751256Syl150051 		 * contains the destination IPv4 address.
63761256Syl150051 		 */
63771256Syl150051 		u32 temp_src_ip = (u32)(spdm_line_arr[1] >> 32);
63781256Syl150051 		u32 temp_dst_ip = (u32)(spdm_line_arr[1] & 0xffffffff);
63791256Syl150051 
63801256Syl150051 		if ((temp_src_ip != src_ip->ipv4.addr) ||
63811256Syl150051 		    (temp_dst_ip != dst_ip->ipv4.addr)) {
63821256Syl150051 			xge_debug_device(XGE_ERR, "Local SPDM table is not "
63831256Syl150051 				"consistent with the actual one for the spdm "
63846937Sxw161283 				"entry %d ", spdm_entry);
63851256Syl150051 			goto err_exit;
63861256Syl150051 		}
63871256Syl150051 
63881256Syl150051 	} else {
63891256Syl150051 		/*
63901256Syl150051 		 * SPDM line 1 & 2 contains the src IPv6 address.
63911256Syl150051 		 * SPDM line 3 & 4 contains the dst IPv6 address.
63921256Syl150051 		 */
63931256Syl150051 		if ((spdm_line_arr[1] != src_ip->ipv6.addr[0]) ||
63941256Syl150051 		    (spdm_line_arr[2] != src_ip->ipv6.addr[1]) ||
63951256Syl150051 		    (spdm_line_arr[3] != dst_ip->ipv6.addr[0]) ||
63961256Syl150051 		    (spdm_line_arr[4] != dst_ip->ipv6.addr[1])) {
63971256Syl150051 
63981256Syl150051 			/*
63991256Syl150051 			 * Log a warning
64001256Syl150051 			 */
64011256Syl150051 			xge_debug_device(XGE_ERR, "Local SPDM table is not "
64021256Syl150051 				"consistent with the actual one for the spdm "
64036937Sxw161283 				"entry %d ", spdm_entry);
64041256Syl150051 			goto err_exit;
64051256Syl150051 		}
64061256Syl150051 	}
64071256Syl150051 
64081256Syl150051 	/*
64091256Syl150051 	 * Reset the entry_enable bit to zero
64101256Syl150051 	 */
64111256Syl150051 	spdm_line_arr[7] &= ~BIT(63);
64121256Syl150051 
64131256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
64141256Syl150051 		spdm_line_arr[7],
64151256Syl150051 		(void *)((char *)hldev->spdm_mem_base +
64161256Syl150051 		(spdm_entry * 64) + (7 * 8)));
64171256Syl150051 
64181256Syl150051 	/*
64191256Syl150051 	 * Wait for the operation to be completed.
64201256Syl150051 	 */
64211256Syl150051 	if (__hal_device_register_poll(hldev,
64221256Syl150051 		&bar0->rxpic_int_reg, 1,
64231256Syl150051 		XGE_HAL_RX_PIC_INT_REG_SPDM_READY,
64241256Syl150051 		XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
64251256Syl150051 		xge_os_spin_unlock(&hldev->spdm_lock);
64261256Syl150051 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
64271256Syl150051 	}
64281256Syl150051 
64291256Syl150051 	/*
64301256Syl150051 	 * Make the corresponding spdm entry in the local SPDM table
64311256Syl150051 	 * available for future use.
64321256Syl150051 	 */
64331256Syl150051 	hldev->spdm_table[spdm_entry]->in_use = 0;
64341256Syl150051 	xge_os_spin_unlock(&hldev->spdm_lock);
64351256Syl150051 
64361256Syl150051 	return XGE_HAL_OK;
64371256Syl150051 
64381256Syl150051 err_exit:
64391256Syl150051 	xge_os_spin_unlock(&hldev->spdm_lock);
64401256Syl150051 	return XGE_HAL_ERR_SPDM_TABLE_DATA_INCONSISTENT;
64411256Syl150051 }
64421256Syl150051 
64431256Syl150051 /*
64441256Syl150051  * __hal_device_rti_set
64451256Syl150051  * @ring: The post_qid of the ring.
64461256Syl150051  * @channel: HAL channel of the ring.
64471256Syl150051  *
64481256Syl150051  * This function stores the RTI value associated for the MSI and
64491256Syl150051  * also unmasks this particular RTI in the rti_mask register.
64501256Syl150051  */
__hal_device_rti_set(int ring_qid,xge_hal_channel_t * channel)64511256Syl150051 static void __hal_device_rti_set(int ring_qid, xge_hal_channel_t *channel)
64521256Syl150051 {
64531256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh;
64541256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
64551256Syl150051 	u64 val64;
64561256Syl150051 
64576937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI ||
64586937Sxw161283 	    hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX)
64596937Sxw161283 		channel->rti = (u8)ring_qid;
64606937Sxw161283 
64611256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
64621256Syl150051 			    &bar0->rx_traffic_mask);
64631256Syl150051 	val64 &= ~BIT(ring_qid);
64641256Syl150051 	xge_os_pio_mem_write64(hldev->pdev,
64651256Syl150051 			    hldev->regh0, val64,
64661256Syl150051 			    &bar0->rx_traffic_mask);
64671256Syl150051 }
64681256Syl150051 
64691256Syl150051 /*
64701256Syl150051  * __hal_device_tti_set
64711256Syl150051  * @ring: The post_qid of the FIFO.
64721256Syl150051  * @channel: HAL channel the FIFO.
64731256Syl150051  *
64741256Syl150051  * This function stores the TTI value associated for the MSI and
64751256Syl150051  * also unmasks this particular TTI in the tti_mask register.
64761256Syl150051  */
__hal_device_tti_set(int fifo_qid,xge_hal_channel_t * channel)64771256Syl150051 static void __hal_device_tti_set(int fifo_qid, xge_hal_channel_t *channel)
64781256Syl150051 {
64791256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh;
64801256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
64811256Syl150051 	u64 val64;
64821256Syl150051 
64836937Sxw161283 	if (hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSI ||
64846937Sxw161283 	    hldev->config.intr_mode == XGE_HAL_INTR_MODE_MSIX)
64856937Sxw161283 		channel->tti = (u8)fifo_qid;
64866937Sxw161283 
64871256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
64881256Syl150051 			    &bar0->tx_traffic_mask);
64891256Syl150051 	val64 &= ~BIT(fifo_qid);
64901256Syl150051 	xge_os_pio_mem_write64(hldev->pdev,
64911256Syl150051 			    hldev->regh0, val64,
64921256Syl150051 			    &bar0->tx_traffic_mask);
64931256Syl150051 }
64946937Sxw161283 
64951256Syl150051 /**
64961256Syl150051  * xge_hal_channel_msi_set - Associate a RTI with a ring or TTI with a
64971256Syl150051  * FIFO for a given MSI.
64981256Syl150051  * @channelh: HAL channel handle.
64991256Syl150051  * @msi: MSI Number associated with the channel.
65001256Syl150051  * @msi_msg: The MSI message associated with the MSI number above.
65011256Syl150051  *
65021256Syl150051  * This API will associate a given channel (either Ring or FIFO) with the
65031256Syl150051  * given MSI number. It will alo program the Tx_Mat/Rx_Mat tables in the
65041256Syl150051  * hardware to indicate this association to the hardware.
65051256Syl150051  */
65061256Syl150051 xge_hal_status_e
xge_hal_channel_msi_set(xge_hal_channel_h channelh,int msi,u32 msi_msg)65071256Syl150051 xge_hal_channel_msi_set(xge_hal_channel_h channelh, int msi, u32 msi_msg)
65081256Syl150051 {
65091256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
65101256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh;
65111256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
65121256Syl150051 	u64 val64;
65131256Syl150051 
65141256Syl150051 	channel->msi_msg = msi_msg;
65151256Syl150051 	if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
65161256Syl150051 		int ring = channel->post_qid;
65171256Syl150051 		xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Ring: %d,"
65186937Sxw161283 				" MSI: %d", channel->msi_msg, ring, msi);
65191256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
65201256Syl150051 			&bar0->rx_mat);
65211256Syl150051 		val64 |= XGE_HAL_SET_RX_MAT(ring, msi);
65221256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
65231256Syl150051 			&bar0->rx_mat);
65241256Syl150051 		__hal_device_rti_set(ring, channel);
65251256Syl150051 	} else {
65261256Syl150051 		int fifo = channel->post_qid;
65271256Syl150051 		xge_debug_osdep(XGE_TRACE, "MSI Data: 0x%4x, Fifo: %d,"
65286937Sxw161283 				" MSI: %d", channel->msi_msg, fifo, msi);
65291256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
65301256Syl150051 			&bar0->tx_mat[0]);
65311256Syl150051 		val64 |= XGE_HAL_SET_TX_MAT(fifo, msi);
65321256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
65331256Syl150051 			&bar0->tx_mat[0]);
65341256Syl150051 		__hal_device_tti_set(fifo, channel);
65351256Syl150051 	}
65361256Syl150051 
65371256Syl150051 	 return XGE_HAL_OK;
65381256Syl150051 }
65396937Sxw161283 
65406937Sxw161283 /**
65416937Sxw161283  * xge_hal_mask_msix - Begin IRQ processing.
65426937Sxw161283  * @hldev: HAL device handle.
65436937Sxw161283  * @msi_id:  MSI ID
65446937Sxw161283  *
65456937Sxw161283  * The function masks the msix interrupt for the given msi_id
65466937Sxw161283  *
65476937Sxw161283  * Note:
65486937Sxw161283  *
65496937Sxw161283  * Returns: 0,
65506937Sxw161283  * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range
65516937Sxw161283  * status.
65526937Sxw161283  * See also:
65536937Sxw161283  */
65546937Sxw161283 xge_hal_status_e
xge_hal_mask_msix(xge_hal_device_h devh,int msi_id)65556937Sxw161283 xge_hal_mask_msix(xge_hal_device_h devh, int msi_id)
65566937Sxw161283 {
65576937Sxw161283 	xge_hal_status_e  status = XGE_HAL_OK;
65586937Sxw161283 	xge_hal_device_t *hldev  = (xge_hal_device_t *)devh;
65596937Sxw161283 	u32              *bar2   = (u32 *)hldev->bar2;
65606937Sxw161283 	u32               val32;
65616937Sxw161283 
65626937Sxw161283 	xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES);
65636937Sxw161283 
65646937Sxw161283 	val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]);
65656937Sxw161283 	val32 |= 1;
65666937Sxw161283 	xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]);
65676937Sxw161283 	return status;
65686937Sxw161283 }
65696937Sxw161283 
65706937Sxw161283 /**
65716937Sxw161283  * xge_hal_mask_msix - Begin IRQ processing.
65726937Sxw161283  * @hldev: HAL device handle.
65736937Sxw161283  * @msi_id:  MSI ID
65746937Sxw161283  *
65756937Sxw161283  * The function masks the msix interrupt for the given msi_id
65766937Sxw161283  *
65776937Sxw161283  * Note:
65786937Sxw161283  *
65796937Sxw161283  * Returns: 0,
65806937Sxw161283  * Otherwise, XGE_HAL_ERR_WRONG_IRQ if the msix index is out of range
65816937Sxw161283  * status.
65826937Sxw161283  * See also:
65836937Sxw161283  */
65846937Sxw161283 xge_hal_status_e
xge_hal_unmask_msix(xge_hal_device_h devh,int msi_id)65856937Sxw161283 xge_hal_unmask_msix(xge_hal_device_h devh, int msi_id)
65866937Sxw161283 {
65876937Sxw161283 	xge_hal_status_e  status = XGE_HAL_OK;
65886937Sxw161283 	xge_hal_device_t *hldev  = (xge_hal_device_t *)devh;
65896937Sxw161283 	u32              *bar2   = (u32 *)hldev->bar2;
65906937Sxw161283 	u32               val32;
65916937Sxw161283 
65926937Sxw161283 	xge_assert(msi_id < XGE_HAL_MAX_MSIX_MESSAGES);
65936937Sxw161283 
65946937Sxw161283 	val32 = xge_os_pio_mem_read32(hldev->pdev, hldev->regh2, &bar2[msi_id*4+3]);
65956937Sxw161283 	val32 &= ~1;
65966937Sxw161283 	xge_os_pio_mem_write32(hldev->pdev, hldev->regh2, val32, &bar2[msi_id*4+3]);
65976937Sxw161283 	return status;
65986937Sxw161283 }
65996937Sxw161283 
66001256Syl150051 /*
66016937Sxw161283  * __hal_set_msix_vals
66021256Syl150051  * @devh: HAL device handle.
66031256Syl150051  * @msix_value: 32bit MSI-X value transferred across PCI to @msix_address.
66041256Syl150051  *              Filled in by this function.
66051256Syl150051  * @msix_address: 32bit MSI-X DMA address.
66061256Syl150051  *              Filled in by this function.
66071256Syl150051  * @msix_idx: index that corresponds to the (@msix_value, @msix_address)
66081256Syl150051  *            entry in the table of MSI-X (value, address) pairs.
66091256Syl150051  *
66101256Syl150051  * This function will program the hardware associating the given
66111256Syl150051  * address/value cobination to the specified msi number.
66121256Syl150051  */
__hal_set_msix_vals(xge_hal_device_h devh,u32 * msix_value,u64 * msix_addr,int msix_idx)66136937Sxw161283 static void __hal_set_msix_vals (xge_hal_device_h devh,
66141256Syl150051 				 u32 *msix_value,
66151256Syl150051 				 u64 *msix_addr,
66161256Syl150051 				 int msix_idx)
66171256Syl150051 {
66181256Syl150051 	int cnt = 0;
66191256Syl150051 
66201256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
66211256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
66221256Syl150051 	u64 val64;
66231256Syl150051 
66241256Syl150051 	val64 = XGE_HAL_XMSI_NO(msix_idx) | XGE_HAL_XMSI_STROBE;
66251256Syl150051 	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
66261256Syl150051 			(u32)(val64 >> 32), &bar0->xmsi_access);
66271256Syl150051 	__hal_pio_mem_write32_lower(hldev->pdev, hldev->regh0,
66281256Syl150051 				   (u32)(val64), &bar0->xmsi_access);
66291256Syl150051 	do {
66301256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
66311256Syl150051 					    &bar0->xmsi_access);
66321256Syl150051 		if (val64 & XGE_HAL_XMSI_STROBE)
66331256Syl150051 			break;
66341256Syl150051 		cnt++;
66351256Syl150051 		xge_os_mdelay(20);
66361256Syl150051 	} while(cnt < 5);
66371256Syl150051 	*msix_value = (u32)(xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
66381256Syl150051 			     &bar0->xmsi_data));
66391256Syl150051 	*msix_addr = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
66401256Syl150051 			     &bar0->xmsi_address);
66411256Syl150051 }
66421256Syl150051 
66431256Syl150051 /**
66441256Syl150051  * xge_hal_channel_msix_set - Associate MSI-X with a channel.
66451256Syl150051  * @channelh: HAL channel handle.
66461256Syl150051  * @msix_idx: index that corresponds to a particular (@msix_value,
66471256Syl150051  *            @msix_address) entry in the MSI-X table.
66481256Syl150051  *
66491256Syl150051  * This API associates a given channel (either Ring or FIFO) with the
66501256Syl150051  * given MSI-X number. It programs the Xframe's Tx_Mat/Rx_Mat tables
66511256Syl150051  * to indicate this association.
66521256Syl150051  */
66531256Syl150051 xge_hal_status_e
xge_hal_channel_msix_set(xge_hal_channel_h channelh,int msix_idx)66541256Syl150051 xge_hal_channel_msix_set(xge_hal_channel_h channelh, int msix_idx)
66551256Syl150051 {
66561256Syl150051 	xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
66571256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)channel->devh;
66581256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
66591256Syl150051 	u64 val64;
66601256Syl150051 
66611256Syl150051 	 if (channel->type == XGE_HAL_CHANNEL_TYPE_RING) {
66621256Syl150051 		 /* Currently Ring and RTI is one on one. */
66631256Syl150051 		int ring = channel->post_qid;
66641256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
66651256Syl150051 			&bar0->rx_mat);
66661256Syl150051 		val64 |= XGE_HAL_SET_RX_MAT(ring, msix_idx);
66671256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
66681256Syl150051 			&bar0->rx_mat);
66691256Syl150051 		__hal_device_rti_set(ring, channel);
66706937Sxw161283 		hldev->config.ring.queue[channel->post_qid].intr_vector =
66716937Sxw161283 								msix_idx;
66721256Syl150051 	 } else if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) {
66731256Syl150051 		int fifo = channel->post_qid;
66741256Syl150051 		val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
66751256Syl150051 			&bar0->tx_mat[0]);
66761256Syl150051 		val64 |= XGE_HAL_SET_TX_MAT(fifo, msix_idx);
66771256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
66781256Syl150051 			&bar0->tx_mat[0]);
66791256Syl150051 		__hal_device_tti_set(fifo, channel);
66806937Sxw161283 		hldev->config.fifo.queue[channel->post_qid].intr_vector =
66816937Sxw161283 								msix_idx;
66821256Syl150051 	}
66831256Syl150051 	 channel->msix_idx = msix_idx;
66846937Sxw161283 	__hal_set_msix_vals(hldev, &channel->msix_data,
66851256Syl150051 			    &channel->msix_address,
66861256Syl150051 			    channel->msix_idx);
66871256Syl150051 
66881256Syl150051 	 return XGE_HAL_OK;
66891256Syl150051 }
66901256Syl150051 
66911256Syl150051 #if defined(XGE_HAL_CONFIG_LRO)
66921256Syl150051 /**
66931256Syl150051  * xge_hal_lro_terminate - Terminate lro resources.
66941256Syl150051  * @lro_scale: Amount of  lro memory.
66951256Syl150051  * @hldev: Hal device structure.
66961256Syl150051  *
66971256Syl150051  */
66981256Syl150051 void
xge_hal_lro_terminate(u32 lro_scale,xge_hal_device_t * hldev)66991256Syl150051 xge_hal_lro_terminate(u32 lro_scale,
67001256Syl150051 	            xge_hal_device_t *hldev)
67011256Syl150051 {
67021256Syl150051 }
67031256Syl150051 
67041256Syl150051 /**
67051256Syl150051  * xge_hal_lro_init - Initiate lro resources.
67061256Syl150051  * @lro_scale: Amount of  lro memory.
67071256Syl150051  * @hldev: Hal device structure.
67081256Syl150051  * Note: For time being I am using only one LRO per device. Later on size
67091256Syl150051  * will be increased.
67101256Syl150051  */
67116937Sxw161283 
67121256Syl150051 xge_hal_status_e
xge_hal_lro_init(u32 lro_scale,xge_hal_device_t * hldev)67131256Syl150051 xge_hal_lro_init(u32 lro_scale,
67141256Syl150051 	       xge_hal_device_t *hldev)
67151256Syl150051 {
67166937Sxw161283 	int i;
67173115Syl150051 
67183115Syl150051 	if (hldev->config.lro_sg_size == XGE_HAL_DEFAULT_USE_HARDCODE)
67193115Syl150051 		hldev->config.lro_sg_size = XGE_HAL_LRO_DEFAULT_SG_SIZE;
67203115Syl150051 
67213115Syl150051 	if (hldev->config.lro_frm_len == XGE_HAL_DEFAULT_USE_HARDCODE)
67223115Syl150051 		hldev->config.lro_frm_len = XGE_HAL_LRO_DEFAULT_FRM_LEN;
67233115Syl150051 
67246937Sxw161283 	for (i=0; i < XGE_HAL_MAX_RING_NUM; i++)
67256937Sxw161283 	{
67266937Sxw161283 		xge_os_memzero(hldev->lro_desc[i].lro_pool,
67276937Sxw161283 			       sizeof(lro_t) * XGE_HAL_LRO_MAX_BUCKETS);
67286937Sxw161283 
67296937Sxw161283 		hldev->lro_desc[i].lro_next_idx = 0;
67306937Sxw161283 		hldev->lro_desc[i].lro_recent = NULL;
67316937Sxw161283 	}
67321256Syl150051 
67331256Syl150051 	return XGE_HAL_OK;
67341256Syl150051 }
67351256Syl150051 #endif
67361256Syl150051 
67371256Syl150051 
67381256Syl150051 /**
67391256Syl150051  * xge_hal_device_poll - HAL device "polling" entry point.
67403115Syl150051  * @devh: HAL device.
67411256Syl150051  *
67421256Syl150051  * HAL "polling" entry point. Note that this is part of HAL public API.
67431256Syl150051  * Upper-Layer driver _must_ periodically poll HAL via
67441256Syl150051  * xge_hal_device_poll().
67451256Syl150051  *
67461256Syl150051  * HAL uses caller's execution context to serially process accumulated
67471256Syl150051  * slow-path events, such as link state changes and hardware error
67481256Syl150051  * indications.
67491256Syl150051  *
67501256Syl150051  * The rate of polling could be somewhere between 500us to 10ms,
67511256Syl150051  * depending on requirements (e.g., the requirement to support fail-over
67521256Syl150051  * could mean that 500us or even 100us polling interval need to be used).
67531256Syl150051  *
67541256Syl150051  * The need and motivation for external polling includes
67551256Syl150051  *
67561256Syl150051  *   - remove the error-checking "burden" from the HAL interrupt handler
67571256Syl150051  *     (see xge_hal_device_handle_irq());
67581256Syl150051  *
67591256Syl150051  *   - remove the potential source of portability issues by _not_
67601256Syl150051  *     implementing separate polling thread within HAL itself.
67611256Syl150051  *
67621256Syl150051  * See also: xge_hal_event_e{}, xge_hal_driver_config_t{}.
67631256Syl150051  * Usage: See ex_slow_path{}.
67641256Syl150051  */
67651256Syl150051 void
xge_hal_device_poll(xge_hal_device_h devh)67661256Syl150051 xge_hal_device_poll(xge_hal_device_h devh)
67671256Syl150051 {
67681256Syl150051 	unsigned char item_buf[sizeof(xge_queue_item_t) +
67691256Syl150051 				XGE_DEFAULT_EVENT_MAX_DATA_SIZE];
67701256Syl150051 	xge_queue_item_t *item = (xge_queue_item_t *)(void *)item_buf;
67711256Syl150051 	xge_queue_status_e qstatus;
67721256Syl150051 	xge_hal_status_e hstatus;
67731256Syl150051 	int i = 0;
67741256Syl150051 	int queue_has_critical_event = 0;
67751256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
67761256Syl150051 
67776937Sxw161283   xge_os_memzero(item_buf, (sizeof(xge_queue_item_t) +
67786937Sxw161283                              XGE_DEFAULT_EVENT_MAX_DATA_SIZE));
67796937Sxw161283 
67801256Syl150051 _again:
67811256Syl150051 	if (!hldev->is_initialized ||
67821256Syl150051 	    hldev->terminating ||
67831256Syl150051 	    hldev->magic != XGE_HAL_MAGIC)
67841256Syl150051 		return;
67851256Syl150051 
67863115Syl150051 	if(hldev->stats.sw_dev_err_stats.xpak_counter.tick_period < 72000)
67873115Syl150051 	{
67883115Syl150051 		/*
67893115Syl150051 	 	 * Wait for an Hour
67903115Syl150051 	 	 */
67913115Syl150051 		hldev->stats.sw_dev_err_stats.xpak_counter.tick_period++;
67923115Syl150051 	} else {
67933115Syl150051 		/*
67943115Syl150051 		 * Logging Error messages in the excess temperature,
67953115Syl150051 		 * Bias current, laser ouput for three cycle
67963115Syl150051 		 */
67973115Syl150051 		__hal_updt_stats_xpak(hldev);
67983115Syl150051 		hldev->stats.sw_dev_err_stats.xpak_counter.tick_period = 0;
67993115Syl150051 	}
68003115Syl150051 
68011256Syl150051 	if (!queue_has_critical_event)
68021256Syl150051 	        queue_has_critical_event =
68031256Syl150051 			__queue_get_reset_critical(hldev->queueh);
68041256Syl150051 
68051256Syl150051 	hldev->in_poll = 1;
68061256Syl150051 	while (i++ < XGE_HAL_DRIVER_QUEUE_CONSUME_MAX || queue_has_critical_event) {
68071256Syl150051 
68081256Syl150051 		qstatus = xge_queue_consume(hldev->queueh,
68091256Syl150051 				    XGE_DEFAULT_EVENT_MAX_DATA_SIZE,
68101256Syl150051 				    item);
68111256Syl150051 		if (qstatus == XGE_QUEUE_IS_EMPTY)
68121256Syl150051 			break;
68131256Syl150051 
68141256Syl150051 		xge_debug_queue(XGE_TRACE,
68153115Syl150051 			 "queueh 0x"XGE_OS_LLXFMT" consumed event: %d ctxt 0x"
68163115Syl150051 			 XGE_OS_LLXFMT, (u64)(ulong_t)hldev->queueh, item->event_type,
68171256Syl150051 			 (u64)(ulong_t)item->context);
68181256Syl150051 
68191256Syl150051 		if (!hldev->is_initialized ||
68201256Syl150051 		    hldev->magic != XGE_HAL_MAGIC) {
68211256Syl150051 			hldev->in_poll = 0;
68221256Syl150051 			return;
68231256Syl150051 		}
68241256Syl150051 
68251256Syl150051 		switch (item->event_type) {
68261256Syl150051 		case XGE_HAL_EVENT_LINK_IS_UP: {
68271256Syl150051 			if (!queue_has_critical_event &&
68281256Syl150051 			    g_xge_hal_driver->uld_callbacks.link_up) {
68291256Syl150051 				g_xge_hal_driver->uld_callbacks.link_up(
68301256Syl150051 					hldev->upper_layer_info);
68311256Syl150051 				hldev->link_state = XGE_HAL_LINK_UP;
68321256Syl150051 			}
68331256Syl150051 		} break;
68341256Syl150051 		case XGE_HAL_EVENT_LINK_IS_DOWN: {
68351256Syl150051 			if (!queue_has_critical_event &&
68361256Syl150051 			    g_xge_hal_driver->uld_callbacks.link_down) {
68371256Syl150051 				g_xge_hal_driver->uld_callbacks.link_down(
68381256Syl150051 					hldev->upper_layer_info);
68391256Syl150051 				hldev->link_state = XGE_HAL_LINK_DOWN;
68401256Syl150051 			}
68411256Syl150051 		} break;
68421256Syl150051 		case XGE_HAL_EVENT_SERR:
68431256Syl150051 		case XGE_HAL_EVENT_ECCERR:
68441256Syl150051 		case XGE_HAL_EVENT_PARITYERR:
68451256Syl150051 		case XGE_HAL_EVENT_TARGETABORT:
68461256Syl150051 		case XGE_HAL_EVENT_SLOT_FREEZE: {
68471256Syl150051 			void *item_data = xge_queue_item_data(item);
68483115Syl150051 			xge_hal_event_e event_type = item->event_type;
68491256Syl150051 			u64 val64 = *((u64*)item_data);
68501256Syl150051 
68511256Syl150051 			if (event_type != XGE_HAL_EVENT_SLOT_FREEZE)
68521256Syl150051 				if (xge_hal_device_is_slot_freeze(hldev))
68531256Syl150051 					event_type = XGE_HAL_EVENT_SLOT_FREEZE;
68541256Syl150051 			if (g_xge_hal_driver->uld_callbacks.crit_err) {
68551256Syl150051 			    g_xge_hal_driver->uld_callbacks.crit_err(
68561256Syl150051 					hldev->upper_layer_info,
68571256Syl150051 					event_type,
68581256Syl150051 					val64);
68591256Syl150051 				/* handle one critical event per poll cycle */
68601256Syl150051 				hldev->in_poll = 0;
68611256Syl150051 				return;
68621256Syl150051 			}
68631256Syl150051 		} break;
68641256Syl150051 		default: {
68651256Syl150051 			xge_debug_queue(XGE_TRACE,
68661256Syl150051 				"got non-HAL event %d",
68671256Syl150051 				item->event_type);
68681256Syl150051 		} break;
68691256Syl150051 		}
68701256Syl150051 
68711256Syl150051 		/* broadcast this event */
68721256Syl150051 		if (g_xge_hal_driver->uld_callbacks.event)
68731256Syl150051 			g_xge_hal_driver->uld_callbacks.event(item);
68741256Syl150051 	}
68751256Syl150051 
68761256Syl150051 	if (g_xge_hal_driver->uld_callbacks.before_device_poll) {
68771256Syl150051 		if (g_xge_hal_driver->uld_callbacks.before_device_poll(
68781256Syl150051 					     hldev) != 0) {
68791256Syl150051 			hldev->in_poll = 0;
68801256Syl150051 			return;
68811256Syl150051 		}
68821256Syl150051 	}
68831256Syl150051 
68841256Syl150051 	hstatus = __hal_device_poll(hldev);
68851256Syl150051 	if (g_xge_hal_driver->uld_callbacks.after_device_poll)
68861256Syl150051 	    g_xge_hal_driver->uld_callbacks.after_device_poll(hldev);
68871256Syl150051 
68881256Syl150051 	/*
68891256Syl150051 	 * handle critical error right away:
68901256Syl150051 	 * - walk the device queue again
68911256Syl150051 	 * - drop non-critical events, if any
68921256Syl150051 	 * - look for the 1st critical
68931256Syl150051 	 */
68941256Syl150051 	if (hstatus == XGE_HAL_ERR_CRITICAL) {
68951256Syl150051 	        queue_has_critical_event = 1;
68961256Syl150051 		goto _again;
68971256Syl150051 	}
68981256Syl150051 
68991256Syl150051 	hldev->in_poll = 0;
69001256Syl150051 }
69011256Syl150051 
69021256Syl150051 /**
69031256Syl150051  * xge_hal_rts_rth_init - Set enhanced mode for  RTS hashing.
69041256Syl150051  * @hldev: HAL device handle.
69051256Syl150051  *
69061256Syl150051  * This function is used to set the adapter to enhanced mode.
69071256Syl150051  *
69081256Syl150051  * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set().
69091256Syl150051  */
69101256Syl150051 void
xge_hal_rts_rth_init(xge_hal_device_t * hldev)69111256Syl150051 xge_hal_rts_rth_init(xge_hal_device_t *hldev)
69121256Syl150051 {
69131256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
69141256Syl150051 	u64 val64;
69151256Syl150051 
69161256Syl150051 	/*
69171256Syl150051 	 * Set the receive traffic steering mode from default(classic)
69181256Syl150051 	 * to enhanced.
69191256Syl150051 	 */
69201256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
69211256Syl150051 				      &bar0->rts_ctrl);
69221256Syl150051 	val64 |= XGE_HAL_RTS_CTRL_ENHANCED_MODE;
69231256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
69241256Syl150051 			       val64, &bar0->rts_ctrl);
69251256Syl150051 }
69261256Syl150051 
69271256Syl150051 /**
69281256Syl150051  * xge_hal_rts_rth_clr - Clear RTS hashing.
69291256Syl150051  * @hldev: HAL device handle.
69301256Syl150051  *
69311256Syl150051  * This function is used to clear all RTS hashing related stuff.
69321256Syl150051  * It brings the adapter out from enhanced mode to classic mode.
69331256Syl150051  * It also clears RTS_RTH_CFG register i.e clears hash type, function etc.
69341256Syl150051  *
69351256Syl150051  * See also: xge_hal_rts_rth_set(), xge_hal_rts_rth_itable_set().
69361256Syl150051  */
69371256Syl150051 void
xge_hal_rts_rth_clr(xge_hal_device_t * hldev)69381256Syl150051 xge_hal_rts_rth_clr(xge_hal_device_t *hldev)
69391256Syl150051 {
69401256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
69411256Syl150051 	u64 val64;
69421256Syl150051 
69431256Syl150051 	/*
69441256Syl150051 	 * Set the receive traffic steering mode from default(classic)
69451256Syl150051 	 * to enhanced.
69461256Syl150051 	 */
69471256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
69481256Syl150051 				      &bar0->rts_ctrl);
69491256Syl150051 	val64 &=  ~XGE_HAL_RTS_CTRL_ENHANCED_MODE;
69501256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
69511256Syl150051 			       val64, &bar0->rts_ctrl);
69521256Syl150051 	val64 = 0;
69531256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
69541256Syl150051 			       &bar0->rts_rth_cfg);
69551256Syl150051 }
69561256Syl150051 
69571256Syl150051 /**
69581256Syl150051  * xge_hal_rts_rth_set - Set/configure RTS hashing.
69591256Syl150051  * @hldev: HAL device handle.
69601256Syl150051  * @def_q: default queue
69611256Syl150051  * @hash_type: hash type i.e TcpIpV4, TcpIpV6 etc.
69621256Syl150051  * @bucket_size: no of least significant bits to be used for hashing.
69631256Syl150051  *
69641256Syl150051  * Used to set/configure all RTS hashing related stuff.
69651256Syl150051  * - set the steering mode to enhanced.
69661256Syl150051  * - set hash function i.e algo selection.
69671256Syl150051  * - set the default queue.
69681256Syl150051  *
69691256Syl150051  * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set().
69701256Syl150051  */
69711256Syl150051 void
xge_hal_rts_rth_set(xge_hal_device_t * hldev,u8 def_q,u64 hash_type,u16 bucket_size)69721256Syl150051 xge_hal_rts_rth_set(xge_hal_device_t *hldev, u8 def_q, u64 hash_type,
69731256Syl150051 		    u16 bucket_size)
69741256Syl150051 {
69751256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
69761256Syl150051 	u64 val64;
69771256Syl150051 
69781256Syl150051 	val64 = XGE_HAL_RTS_DEFAULT_Q(def_q);
69791256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
69801256Syl150051 			       &bar0->rts_default_q);
69811256Syl150051 
69821256Syl150051 	val64 = hash_type;
69831256Syl150051 	val64 |= XGE_HAL_RTS_RTH_EN;
69841256Syl150051 	val64 |= XGE_HAL_RTS_RTH_BUCKET_SIZE(bucket_size);
69851256Syl150051 	val64 |= XGE_HAL_RTS_RTH_ALG_SEL_MS;
69861256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
69871256Syl150051 			       &bar0->rts_rth_cfg);
69881256Syl150051 }
69891256Syl150051 
69901256Syl150051 /**
69911256Syl150051  * xge_hal_rts_rth_start - Start RTS hashing.
69921256Syl150051  * @hldev: HAL device handle.
69931256Syl150051  *
69941256Syl150051  * Used to Start RTS hashing .
69951256Syl150051  *
69961256Syl150051  * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start.
69971256Syl150051  */
69981256Syl150051 void
xge_hal_rts_rth_start(xge_hal_device_t * hldev)69991256Syl150051 xge_hal_rts_rth_start(xge_hal_device_t *hldev)
70001256Syl150051 {
70011256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
70021256Syl150051 	u64 val64;
70031256Syl150051 
70041256Syl150051 
70051256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
70061256Syl150051 				      &bar0->rts_rth_cfg);
70071256Syl150051 	val64 |= XGE_HAL_RTS_RTH_EN;
70081256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
70091256Syl150051 			       &bar0->rts_rth_cfg);
70101256Syl150051 }
70111256Syl150051 
70121256Syl150051 /**
70131256Syl150051  * xge_hal_rts_rth_stop - Stop the RTS hashing.
70141256Syl150051  * @hldev: HAL device handle.
70151256Syl150051  *
70161256Syl150051  * Used to Staop RTS hashing .
70171256Syl150051  *
70181256Syl150051  * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_itable_set(), xge_hal_rts_rth_start.
70191256Syl150051  */
70201256Syl150051 void
xge_hal_rts_rth_stop(xge_hal_device_t * hldev)70211256Syl150051 xge_hal_rts_rth_stop(xge_hal_device_t *hldev)
70221256Syl150051 {
70231256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
70241256Syl150051 	u64 val64;
70251256Syl150051 
70261256Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
70271256Syl150051 				      &bar0->rts_rth_cfg);
70281256Syl150051 	val64 &=  ~XGE_HAL_RTS_RTH_EN;
70291256Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
70301256Syl150051 			       &bar0->rts_rth_cfg);
70311256Syl150051 }
70321256Syl150051 
70331256Syl150051 /**
70341256Syl150051  * xge_hal_rts_rth_itable_set - Set/configure indirection table (IT).
70351256Syl150051  * @hldev: HAL device handle.
70361256Syl150051  * @itable: Pointer to the indirection table
70371256Syl150051  * @itable_size: no of least significant bits to be used for hashing
70381256Syl150051  *
70391256Syl150051  * Used to set/configure indirection table.
70401256Syl150051  * It enables the required no of entries in the IT.
70411256Syl150051  * It adds entries to the IT.
70421256Syl150051  *
70431256Syl150051  * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set().
70441256Syl150051  */
70451256Syl150051 xge_hal_status_e
xge_hal_rts_rth_itable_set(xge_hal_device_t * hldev,u8 * itable,u32 itable_size)70461256Syl150051 xge_hal_rts_rth_itable_set(xge_hal_device_t *hldev, u8 *itable, u32 itable_size)
70471256Syl150051 {
70481256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void	*)hldev->bar0;
70491256Syl150051 	u64 val64;
70501256Syl150051 	u32 idx;
70511256Syl150051 
70521256Syl150051 	for (idx = 0; idx < itable_size; idx++) {
70531256Syl150051 		val64 = XGE_HAL_RTS_RTH_MAP_MEM_DATA_ENTRY_EN |
70541256Syl150051 			XGE_HAL_RTS_RTH_MAP_MEM_DATA(itable[idx]);
70551256Syl150051 
70561256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
70571256Syl150051 				       &bar0->rts_rth_map_mem_data);
70581256Syl150051 
70591256Syl150051 		/* execute */
70601256Syl150051 		val64 = (XGE_HAL_RTS_RTH_MAP_MEM_CTRL_WE |
70611256Syl150051 			 XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE |
70621256Syl150051 			 XGE_HAL_RTS_RTH_MAP_MEM_CTRL_OFFSET(idx));
70631256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
70641256Syl150051 				       &bar0->rts_rth_map_mem_ctrl);
70651256Syl150051 
70661256Syl150051 		/* poll until done */
70671256Syl150051 		if (__hal_device_register_poll(hldev,
70681256Syl150051 		       &bar0->rts_rth_map_mem_ctrl, 0,
70691256Syl150051 		       XGE_HAL_RTS_RTH_MAP_MEM_CTRL_STROBE,
70701256Syl150051 		       XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
70711256Syl150051 			/* upper layer may require to repeat */
70721256Syl150051 			return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
70731256Syl150051 		}
70741256Syl150051 	}
70751256Syl150051 
70761256Syl150051 	return XGE_HAL_OK;
70771256Syl150051 }
70781256Syl150051 
70791256Syl150051 
70801256Syl150051 /**
70811256Syl150051  * xge_hal_device_rts_rth_key_set - Configure 40byte secret for hash calc.
70821256Syl150051  *
70831256Syl150051  * @hldev: HAL device handle.
70841256Syl150051  * @KeySize: Number of 64-bit words
70851256Syl150051  * @Key: upto 40-byte array of 8-bit values
70861256Syl150051  * This function configures the 40-byte secret which is used for hash
70871256Syl150051  * calculation.
70881256Syl150051  *
70891256Syl150051  * See also: xge_hal_rts_rth_clr(), xge_hal_rts_rth_set().
70901256Syl150051  */
70911256Syl150051 void
xge_hal_device_rts_rth_key_set(xge_hal_device_t * hldev,u8 KeySize,u8 * Key)70921256Syl150051 xge_hal_device_rts_rth_key_set(xge_hal_device_t *hldev, u8 KeySize, u8 *Key)
70931256Syl150051 {
70941256Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *) hldev->bar0;
70951256Syl150051 	u64 val64;
70961256Syl150051 	u32 entry, nreg, i;
70971256Syl150051 
70981256Syl150051 	entry = 0;
70991256Syl150051 	nreg = 0;
71001256Syl150051 
71011256Syl150051 	while( KeySize ) {
71021256Syl150051 		val64 = 0;
71031256Syl150051 		for ( i = 0; i < 8 ; i++) {
71041256Syl150051 			/* Prepare 64-bit word for 'nreg' containing 8 keys. */
71051256Syl150051 			if (i)
71061256Syl150051 				val64 <<= 8;
71071256Syl150051 			val64 |= Key[entry++];
71081256Syl150051 		}
71091256Syl150051 
71101256Syl150051 		KeySize--;
71111256Syl150051 
71121256Syl150051 		/* temp64 = XGE_HAL_RTH_HASH_MASK_n(val64, (n<<3), (n<<3)+7);*/
71131256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
71141256Syl150051 				       &bar0->rts_rth_hash_mask[nreg++]);
71151256Syl150051 	}
71161256Syl150051 
71171256Syl150051 	while( nreg < 5 ) {
71181256Syl150051 		/* Clear the rest if key is less than 40 bytes */
71191256Syl150051 		val64 = 0;
71201256Syl150051 		xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
71211256Syl150051 				       &bar0->rts_rth_hash_mask[nreg++]);
71221256Syl150051 	}
71231256Syl150051 }
71241256Syl150051 
71251256Syl150051 
71261256Syl150051 /**
71271256Syl150051  * xge_hal_device_is_closed - Device is closed
71281256Syl150051  *
71293115Syl150051  * @devh: HAL device handle.
71301256Syl150051  */
71311256Syl150051 int
xge_hal_device_is_closed(xge_hal_device_h devh)71321256Syl150051 xge_hal_device_is_closed(xge_hal_device_h devh)
71331256Syl150051 {
71341256Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
71351256Syl150051 
71361256Syl150051 	if (xge_list_is_empty(&hldev->fifo_channels) &&
71371256Syl150051 	    xge_list_is_empty(&hldev->ring_channels))
71381256Syl150051 		return 1;
71391256Syl150051 
71401256Syl150051 	return 0;
71411256Syl150051 }
71421256Syl150051 
71433115Syl150051 xge_hal_status_e
xge_hal_device_rts_section_enable(xge_hal_device_h devh,int index)71443115Syl150051 xge_hal_device_rts_section_enable(xge_hal_device_h devh, int index)
71453115Syl150051 {
71463115Syl150051 	u64 val64;
71473115Syl150051 	int section;
71483115Syl150051 	int max_addr = XGE_HAL_MAX_MAC_ADDRESSES;
71493115Syl150051 
71503115Syl150051 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
71513115Syl150051 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)(void *)hldev->bar0;
71523115Syl150051 
71533115Syl150051 	if (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)
71543115Syl150051 		max_addr = XGE_HAL_MAX_MAC_ADDRESSES_HERC;
71553115Syl150051 
71563115Syl150051 	if ( index >= max_addr )
71573115Syl150051 		return XGE_HAL_ERR_OUT_OF_MAC_ADDRESSES;
71583115Syl150051 
71593115Syl150051 	/*
71603115Syl150051 	 * Calculate the section value
71613115Syl150051 	 */
71623115Syl150051 	section = index / 32;
71633115Syl150051 
71646937Sxw161283         xge_debug_device(XGE_TRACE, "the Section value is %d ", section);
71653115Syl150051 
71663115Syl150051 	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
71673115Syl150051 				&bar0->rts_mac_cfg);
71683115Syl150051 	switch(section)
71693115Syl150051 	{
71703115Syl150051 		case 0:
71713115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT0_EN;
71723115Syl150051 			break;
71733115Syl150051 		case 1:
71743115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT1_EN;
71753115Syl150051 			break;
71763115Syl150051 		case 2:
71773115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT2_EN;
71783115Syl150051 			break;
71793115Syl150051 		case 3:
71803115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT3_EN;
71813115Syl150051 			break;
71823115Syl150051 		case 4:
71833115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT4_EN;
71843115Syl150051 			break;
71853115Syl150051 		case 5:
71863115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT5_EN;
71873115Syl150051 			break;
71883115Syl150051 		case 6:
71893115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT6_EN;
71903115Syl150051 			break;
71913115Syl150051 		case 7:
71923115Syl150051 			val64 |=  XGE_HAL_RTS_MAC_SECT7_EN;
71933115Syl150051 			break;
71943115Syl150051 		default:
71956937Sxw161283 			xge_debug_device(XGE_ERR, "Invalid Section value %d "
71963115Syl150051 					, section);
71973115Syl150051         }
71983115Syl150051 
71993115Syl150051 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
72003115Syl150051 				val64, &bar0->rts_mac_cfg);
72013115Syl150051 	return XGE_HAL_OK;
72023115Syl150051 }
72033115Syl150051 
72046937Sxw161283 /*
72056937Sxw161283  * xge_hal_fix_rldram_ecc_error
72066937Sxw161283  * @hldev: private member of the device structure.
72076937Sxw161283  *
72086937Sxw161283  * SXE-02-010. This function will turn OFF the ECC error reporting for the
72096937Sxw161283  * interface bet'n external Micron RLDRAM II device and memory controller.
72106937Sxw161283  * The error would have been reported in RLD_ECC_DB_ERR_L and RLD_ECC_DB_ERR_U
72116937Sxw161283  * fileds of MC_ERR_REG register. Issue reported by HP-Unix folks during the
72126937Sxw161283  * qualification of Herc.
72136937Sxw161283  */
72143115Syl150051 xge_hal_status_e
xge_hal_fix_rldram_ecc_error(xge_hal_device_t * hldev)72156937Sxw161283 xge_hal_fix_rldram_ecc_error(xge_hal_device_t *hldev)
72163115Syl150051 {
72176937Sxw161283 	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
72186937Sxw161283 	u64 val64;
72196937Sxw161283 
72206937Sxw161283 	// Enter Test Mode.
72216937Sxw161283 	val64 = XGE_HAL_MC_RLDRAM_TEST_MODE;
72226937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72236937Sxw161283 	    &bar0->mc_rldram_test_ctrl);
72246937Sxw161283 
72256937Sxw161283 	// Enable fg/bg tests.
72266937Sxw161283 	val64 = 0x0100000000000000ULL;
72276937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72286937Sxw161283 	    &bar0->mc_driver);
72296937Sxw161283 
72306937Sxw161283 	// Enable RLDRAM configuration.
72316937Sxw161283 	val64 = 0x0000000000017B00ULL;
72326937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72336937Sxw161283 	    &bar0->mc_rldram_mrs);
72346937Sxw161283 
72356937Sxw161283 	// Enable RLDRAM queues.
72366937Sxw161283 	val64 = 0x0000000001017B00ULL;
72376937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72386937Sxw161283 	    &bar0->mc_rldram_mrs);
72396937Sxw161283 
72406937Sxw161283 	// Setup test ranges.
72416937Sxw161283 	val64 = 0x00000000001E0100ULL;
72426937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72436937Sxw161283 	    &bar0->mc_rldram_test_add);
72446937Sxw161283 
72456937Sxw161283 	val64 = 0x00000100001F0100ULL;
72466937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72476937Sxw161283 	    &bar0->mc_rldram_test_add_bkg);
72486937Sxw161283 
72496937Sxw161283 	// Start Reads.
72506937Sxw161283 	val64 = 0x0001000000010000ULL;
72516937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72526937Sxw161283 	    &bar0->mc_rldram_test_ctrl);
72536937Sxw161283 
72546937Sxw161283 	if (__hal_device_register_poll(hldev, &bar0->mc_rldram_test_ctrl, 1,
72556937Sxw161283 	    XGE_HAL_MC_RLDRAM_TEST_DONE,
72566937Sxw161283 	    XGE_HAL_DEVICE_CMDMEM_WAIT_MAX_MILLIS) != XGE_HAL_OK) {
72576937Sxw161283 		return XGE_HAL_INF_MEM_STROBE_CMD_EXECUTING;
72586937Sxw161283 	}
72596937Sxw161283 
72606937Sxw161283 	// Exit test mode.
72616937Sxw161283 	val64 = 0x0000000000000000ULL;
72626937Sxw161283 	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
72636937Sxw161283 	    &bar0->mc_rldram_test_ctrl);
72643115Syl150051 
72653115Syl150051 	return XGE_HAL_OK;
72663115Syl150051 }
72677656SSherry.Moore@Sun.COM 
72687656SSherry.Moore@Sun.COM /*
72697656SSherry.Moore@Sun.COM  * xge_hal_device_quiesce
72707656SSherry.Moore@Sun.COM  * @hldev: HAL device object
72717656SSherry.Moore@Sun.COM  * @devh : HAL device handle
72727656SSherry.Moore@Sun.COM  *
72737656SSherry.Moore@Sun.COM  * This is called by xge_quiesce to quiesce the device.
72747656SSherry.Moore@Sun.COM  */
72757656SSherry.Moore@Sun.COM void
xge_hal_device_quiesce(xge_hal_device_t * hldev,xge_hal_device_h devh)72767656SSherry.Moore@Sun.COM xge_hal_device_quiesce(xge_hal_device_t *hldev, xge_hal_device_h devh)
72777656SSherry.Moore@Sun.COM {
72787656SSherry.Moore@Sun.COM 	/* Turn off debugging */
72797656SSherry.Moore@Sun.COM 	g_xge_hal_driver->debug_level = XGE_NONE;
72807656SSherry.Moore@Sun.COM 	g_level = &(g_xge_hal_driver->debug_level);
72817656SSherry.Moore@Sun.COM 
72827656SSherry.Moore@Sun.COM 	/* Disable device */
72837656SSherry.Moore@Sun.COM 	(void) xge_hal_device_disable(devh);
72847656SSherry.Moore@Sun.COM 
72857656SSherry.Moore@Sun.COM 	/* Disable Xframe interrupts */
72867656SSherry.Moore@Sun.COM 	xge_hal_device_intr_disable(devh);
72877656SSherry.Moore@Sun.COM }
7288