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