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