• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/net/vxge/
1/******************************************************************************
2 * This software may be used and distributed according to the terms of
3 * the GNU General Public License (GPL), incorporated herein by reference.
4 * Drivers based on or derived from this code fall under the GPL and must
5 * retain the authorship, copyright and license notice.  This file is not
6 * a complete program and may only be used when the entire operating
7 * system is licensed under the GPL.
8 * See the file COPYING in this distribution for more information.
9 *
10 * vxge-traffic.c: Driver for Exar Corp's X3100 Series 10GbE PCIe I/O
11 *                 Virtualized Server Adapter.
12 * Copyright(c) 2002-2010 Exar Corp.
13 ******************************************************************************/
14#include <linux/etherdevice.h>
15
16#include "vxge-traffic.h"
17#include "vxge-config.h"
18#include "vxge-main.h"
19
20/*
21 * vxge_hw_vpath_intr_enable - Enable vpath interrupts.
22 * @vp: Virtual Path handle.
23 *
24 * Enable vpath interrupts. The function is to be executed the last in
25 * vpath initialization sequence.
26 *
27 * See also: vxge_hw_vpath_intr_disable()
28 */
29enum vxge_hw_status vxge_hw_vpath_intr_enable(struct __vxge_hw_vpath_handle *vp)
30{
31	u64 val64;
32
33	struct __vxge_hw_virtualpath *vpath;
34	struct vxge_hw_vpath_reg __iomem *vp_reg;
35	enum vxge_hw_status status = VXGE_HW_OK;
36	if (vp == NULL) {
37		status = VXGE_HW_ERR_INVALID_HANDLE;
38		goto exit;
39	}
40
41	vpath = vp->vpath;
42
43	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
44		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
45		goto exit;
46	}
47
48	vp_reg = vpath->vp_reg;
49
50	writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_reg);
51
52	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
53			&vp_reg->general_errors_reg);
54
55	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
56			&vp_reg->pci_config_errors_reg);
57
58	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
59			&vp_reg->mrpcim_to_vpath_alarm_reg);
60
61	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
62			&vp_reg->srpcim_to_vpath_alarm_reg);
63
64	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
65			&vp_reg->vpath_ppif_int_status);
66
67	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
68			&vp_reg->srpcim_msg_to_vpath_reg);
69
70	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
71			&vp_reg->vpath_pcipif_int_status);
72
73	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
74			&vp_reg->prc_alarm_reg);
75
76	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
77			&vp_reg->wrdma_alarm_status);
78
79	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
80			&vp_reg->asic_ntwk_vp_err_reg);
81
82	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
83			&vp_reg->xgmac_vp_int_status);
84
85	val64 = readq(&vp_reg->vpath_general_int_status);
86
87	/* Mask unwanted interrupts */
88
89	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
90			&vp_reg->vpath_pcipif_int_mask);
91
92	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
93			&vp_reg->srpcim_msg_to_vpath_mask);
94
95	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
96			&vp_reg->srpcim_to_vpath_alarm_mask);
97
98	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
99			&vp_reg->mrpcim_to_vpath_alarm_mask);
100
101	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
102			&vp_reg->pci_config_errors_mask);
103
104	/* Unmask the individual interrupts */
105
106	writeq((u32)vxge_bVALn((VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO1_OVRFLOW|
107		VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO2_OVRFLOW|
108		VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ|
109		VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR), 0, 32),
110		&vp_reg->general_errors_mask);
111
112	__vxge_hw_pio_mem_write32_upper(
113		(u32)vxge_bVALn((VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_OVRWR|
114		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_OVRWR|
115		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_POISON|
116		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_POISON|
117		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO1_DMA_ERR|
118		VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO2_DMA_ERR), 0, 32),
119		&vp_reg->kdfcctl_errors_mask);
120
121	__vxge_hw_pio_mem_write32_upper(0, &vp_reg->vpath_ppif_int_mask);
122
123	__vxge_hw_pio_mem_write32_upper(
124		(u32)vxge_bVALn(VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP, 0, 32),
125		&vp_reg->prc_alarm_mask);
126
127	__vxge_hw_pio_mem_write32_upper(0, &vp_reg->wrdma_alarm_mask);
128	__vxge_hw_pio_mem_write32_upper(0, &vp_reg->xgmac_vp_int_mask);
129
130	if (vpath->hldev->first_vp_id != vpath->vp_id)
131		__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
132			&vp_reg->asic_ntwk_vp_err_mask);
133	else
134		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn((
135		VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_FAULT |
136		VXGE_HW_ASIC_NTWK_VP_ERR_REG_XMACJ_NTWK_REAFFIRMED_OK), 0, 32),
137		&vp_reg->asic_ntwk_vp_err_mask);
138
139	__vxge_hw_pio_mem_write32_upper(0,
140		&vp_reg->vpath_general_int_mask);
141exit:
142	return status;
143
144}
145
146/*
147 * vxge_hw_vpath_intr_disable - Disable vpath interrupts.
148 * @vp: Virtual Path handle.
149 *
150 * Disable vpath interrupts. The function is to be executed the last in
151 * vpath initialization sequence.
152 *
153 * See also: vxge_hw_vpath_intr_enable()
154 */
155enum vxge_hw_status vxge_hw_vpath_intr_disable(
156			struct __vxge_hw_vpath_handle *vp)
157{
158	u64 val64;
159
160	struct __vxge_hw_virtualpath *vpath;
161	enum vxge_hw_status status = VXGE_HW_OK;
162	struct vxge_hw_vpath_reg __iomem *vp_reg;
163	if (vp == NULL) {
164		status = VXGE_HW_ERR_INVALID_HANDLE;
165		goto exit;
166	}
167
168	vpath = vp->vpath;
169
170	if (vpath->vp_open == VXGE_HW_VP_NOT_OPEN) {
171		status = VXGE_HW_ERR_VPATH_NOT_OPEN;
172		goto exit;
173	}
174	vp_reg = vpath->vp_reg;
175
176	__vxge_hw_pio_mem_write32_upper(
177		(u32)VXGE_HW_INTR_MASK_ALL,
178		&vp_reg->vpath_general_int_mask);
179
180	val64 = VXGE_HW_TIM_CLR_INT_EN_VP(1 << (16 - vpath->vp_id));
181
182	writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_mask);
183
184	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
185			&vp_reg->general_errors_mask);
186
187	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
188			&vp_reg->pci_config_errors_mask);
189
190	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
191			&vp_reg->mrpcim_to_vpath_alarm_mask);
192
193	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
194			&vp_reg->srpcim_to_vpath_alarm_mask);
195
196	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
197			&vp_reg->vpath_ppif_int_mask);
198
199	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
200			&vp_reg->srpcim_msg_to_vpath_mask);
201
202	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
203			&vp_reg->vpath_pcipif_int_mask);
204
205	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
206			&vp_reg->wrdma_alarm_mask);
207
208	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
209			&vp_reg->prc_alarm_mask);
210
211	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
212			&vp_reg->xgmac_vp_int_mask);
213
214	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
215			&vp_reg->asic_ntwk_vp_err_mask);
216
217exit:
218	return status;
219}
220
221/**
222 * vxge_hw_channel_msix_mask - Mask MSIX Vector.
223 * @channeh: Channel for rx or tx handle
224 * @msix_id:  MSIX ID
225 *
226 * The function masks the msix interrupt for the given msix_id
227 *
228 * Returns: 0
229 */
230void vxge_hw_channel_msix_mask(struct __vxge_hw_channel *channel, int msix_id)
231{
232
233	__vxge_hw_pio_mem_write32_upper(
234		(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
235		&channel->common_reg->set_msix_mask_vect[msix_id%4]);
236}
237
238/**
239 * vxge_hw_channel_msix_unmask - Unmask the MSIX Vector.
240 * @channeh: Channel for rx or tx handle
241 * @msix_id:  MSI ID
242 *
243 * The function unmasks the msix interrupt for the given msix_id
244 *
245 * Returns: 0
246 */
247void
248vxge_hw_channel_msix_unmask(struct __vxge_hw_channel *channel, int msix_id)
249{
250
251	__vxge_hw_pio_mem_write32_upper(
252		(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
253		&channel->common_reg->clear_msix_mask_vect[msix_id%4]);
254}
255
256/**
257 * vxge_hw_device_set_intr_type - Updates the configuration
258 *		with new interrupt type.
259 * @hldev: HW device handle.
260 * @intr_mode: New interrupt type
261 */
262u32 vxge_hw_device_set_intr_type(struct __vxge_hw_device *hldev, u32 intr_mode)
263{
264
265	if ((intr_mode != VXGE_HW_INTR_MODE_IRQLINE) &&
266	   (intr_mode != VXGE_HW_INTR_MODE_MSIX) &&
267	   (intr_mode != VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) &&
268	   (intr_mode != VXGE_HW_INTR_MODE_DEF))
269		intr_mode = VXGE_HW_INTR_MODE_IRQLINE;
270
271	hldev->config.intr_mode = intr_mode;
272	return intr_mode;
273}
274
275/**
276 * vxge_hw_device_intr_enable - Enable interrupts.
277 * @hldev: HW device handle.
278 * @op: One of the enum vxge_hw_device_intr enumerated values specifying
279 *      the type(s) of interrupts to enable.
280 *
281 * Enable Titan interrupts. The function is to be executed the last in
282 * Titan initialization sequence.
283 *
284 * See also: vxge_hw_device_intr_disable()
285 */
286void vxge_hw_device_intr_enable(struct __vxge_hw_device *hldev)
287{
288	u32 i;
289	u64 val64;
290	u32 val32;
291
292	vxge_hw_device_mask_all(hldev);
293
294	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
295
296		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
297			continue;
298
299		vxge_hw_vpath_intr_enable(
300			VXGE_HW_VIRTUAL_PATH_HANDLE(&hldev->virtual_paths[i]));
301	}
302
303	if (hldev->config.intr_mode == VXGE_HW_INTR_MODE_IRQLINE) {
304		val64 = hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
305			hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX];
306
307		if (val64 != 0) {
308			writeq(val64, &hldev->common_reg->tim_int_status0);
309
310			writeq(~val64, &hldev->common_reg->tim_int_mask0);
311		}
312
313		val32 = hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
314			hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX];
315
316		if (val32 != 0) {
317			__vxge_hw_pio_mem_write32_upper(val32,
318					&hldev->common_reg->tim_int_status1);
319
320			__vxge_hw_pio_mem_write32_upper(~val32,
321					&hldev->common_reg->tim_int_mask1);
322		}
323	}
324
325	val64 = readq(&hldev->common_reg->titan_general_int_status);
326
327	vxge_hw_device_unmask_all(hldev);
328}
329
330/**
331 * vxge_hw_device_intr_disable - Disable Titan interrupts.
332 * @hldev: HW device handle.
333 * @op: One of the enum vxge_hw_device_intr enumerated values specifying
334 *      the type(s) of interrupts to disable.
335 *
336 * Disable Titan interrupts.
337 *
338 * See also: vxge_hw_device_intr_enable()
339 */
340void vxge_hw_device_intr_disable(struct __vxge_hw_device *hldev)
341{
342	u32 i;
343
344	vxge_hw_device_mask_all(hldev);
345
346	/* mask all the tim interrupts */
347	writeq(VXGE_HW_INTR_MASK_ALL, &hldev->common_reg->tim_int_mask0);
348	__vxge_hw_pio_mem_write32_upper(VXGE_HW_DEFAULT_32,
349		&hldev->common_reg->tim_int_mask1);
350
351	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
352
353		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
354			continue;
355
356		vxge_hw_vpath_intr_disable(
357			VXGE_HW_VIRTUAL_PATH_HANDLE(&hldev->virtual_paths[i]));
358	}
359}
360
361/**
362 * vxge_hw_device_mask_all - Mask all device interrupts.
363 * @hldev: HW device handle.
364 *
365 * Mask	all device interrupts.
366 *
367 * See also: vxge_hw_device_unmask_all()
368 */
369void vxge_hw_device_mask_all(struct __vxge_hw_device *hldev)
370{
371	u64 val64;
372
373	val64 = VXGE_HW_TITAN_MASK_ALL_INT_ALARM |
374		VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC;
375
376	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
377				&hldev->common_reg->titan_mask_all_int);
378}
379
380/**
381 * vxge_hw_device_unmask_all - Unmask all device interrupts.
382 * @hldev: HW device handle.
383 *
384 * Unmask all device interrupts.
385 *
386 * See also: vxge_hw_device_mask_all()
387 */
388void vxge_hw_device_unmask_all(struct __vxge_hw_device *hldev)
389{
390	u64 val64 = 0;
391
392	if (hldev->config.intr_mode == VXGE_HW_INTR_MODE_IRQLINE)
393		val64 =  VXGE_HW_TITAN_MASK_ALL_INT_TRAFFIC;
394
395	__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(val64, 0, 32),
396			&hldev->common_reg->titan_mask_all_int);
397}
398
399/**
400 * vxge_hw_device_flush_io - Flush io writes.
401 * @hldev: HW device handle.
402 *
403 * The function	performs a read operation to flush io writes.
404 *
405 * Returns: void
406 */
407void vxge_hw_device_flush_io(struct __vxge_hw_device *hldev)
408{
409	u32 val32;
410
411	val32 = readl(&hldev->common_reg->titan_general_int_status);
412}
413
414/**
415 * vxge_hw_device_begin_irq - Begin IRQ processing.
416 * @hldev: HW device handle.
417 * @skip_alarms: Do not clear the alarms
418 * @reason: "Reason" for the interrupt, the value of Titan's
419 *	general_int_status register.
420 *
421 * The function	performs two actions, It first checks whether (shared IRQ) the
422 * interrupt was raised	by the device. Next, it	masks the device interrupts.
423 *
424 * Note:
425 * vxge_hw_device_begin_irq() does not flush MMIO writes through the
426 * bridge. Therefore, two back-to-back interrupts are potentially possible.
427 *
428 * Returns: 0, if the interrupt	is not "ours" (note that in this case the
429 * device remain enabled).
430 * Otherwise, vxge_hw_device_begin_irq() returns 64bit general adapter
431 * status.
432 */
433enum vxge_hw_status vxge_hw_device_begin_irq(struct __vxge_hw_device *hldev,
434					     u32 skip_alarms, u64 *reason)
435{
436	u32 i;
437	u64 val64;
438	u64 adapter_status;
439	u64 vpath_mask;
440	enum vxge_hw_status ret = VXGE_HW_OK;
441
442	val64 = readq(&hldev->common_reg->titan_general_int_status);
443
444	if (unlikely(!val64)) {
445		/* not Titan interrupt	*/
446		*reason	= 0;
447		ret = VXGE_HW_ERR_WRONG_IRQ;
448		goto exit;
449	}
450
451	if (unlikely(val64 == VXGE_HW_ALL_FOXES)) {
452
453		adapter_status = readq(&hldev->common_reg->adapter_status);
454
455		if (adapter_status == VXGE_HW_ALL_FOXES) {
456
457			__vxge_hw_device_handle_error(hldev,
458				NULL_VPID, VXGE_HW_EVENT_SLOT_FREEZE);
459			*reason	= 0;
460			ret = VXGE_HW_ERR_SLOT_FREEZE;
461			goto exit;
462		}
463	}
464
465	hldev->stats.sw_dev_info_stats.total_intr_cnt++;
466
467	*reason	= val64;
468
469	vpath_mask = hldev->vpaths_deployed >>
470				(64 - VXGE_HW_MAX_VIRTUAL_PATHS);
471
472	if (val64 &
473	    VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_TRAFFIC_INT(vpath_mask)) {
474		hldev->stats.sw_dev_info_stats.traffic_intr_cnt++;
475
476		return VXGE_HW_OK;
477	}
478
479	hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
480
481	if (unlikely(val64 &
482			VXGE_HW_TITAN_GENERAL_INT_STATUS_VPATH_ALARM_INT)) {
483
484		enum vxge_hw_status error_level = VXGE_HW_OK;
485
486		hldev->stats.sw_dev_err_stats.vpath_alarms++;
487
488		for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
489
490			if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
491				continue;
492
493			ret = __vxge_hw_vpath_alarm_process(
494				&hldev->virtual_paths[i], skip_alarms);
495
496			error_level = VXGE_HW_SET_LEVEL(ret, error_level);
497
498			if (unlikely((ret == VXGE_HW_ERR_CRITICAL) ||
499				(ret == VXGE_HW_ERR_SLOT_FREEZE)))
500				break;
501		}
502
503		ret = error_level;
504	}
505exit:
506	return ret;
507}
508
509/*
510 * __vxge_hw_device_handle_link_up_ind
511 * @hldev: HW device handle.
512 *
513 * Link up indication handler. The function is invoked by HW when
514 * Titan indicates that the link is up for programmable amount of time.
515 */
516enum vxge_hw_status
517__vxge_hw_device_handle_link_up_ind(struct __vxge_hw_device *hldev)
518{
519	/*
520	 * If the previous link state is not down, return.
521	 */
522	if (hldev->link_state == VXGE_HW_LINK_UP)
523		goto exit;
524
525	hldev->link_state = VXGE_HW_LINK_UP;
526
527	/* notify driver */
528	if (hldev->uld_callbacks.link_up)
529		hldev->uld_callbacks.link_up(hldev);
530exit:
531	return VXGE_HW_OK;
532}
533
534/*
535 * __vxge_hw_device_handle_link_down_ind
536 * @hldev: HW device handle.
537 *
538 * Link down indication handler. The function is invoked by HW when
539 * Titan indicates that the link is down.
540 */
541enum vxge_hw_status
542__vxge_hw_device_handle_link_down_ind(struct __vxge_hw_device *hldev)
543{
544	/*
545	 * If the previous link state is not down, return.
546	 */
547	if (hldev->link_state == VXGE_HW_LINK_DOWN)
548		goto exit;
549
550	hldev->link_state = VXGE_HW_LINK_DOWN;
551
552	/* notify driver */
553	if (hldev->uld_callbacks.link_down)
554		hldev->uld_callbacks.link_down(hldev);
555exit:
556	return VXGE_HW_OK;
557}
558
559/**
560 * __vxge_hw_device_handle_error - Handle error
561 * @hldev: HW device
562 * @vp_id: Vpath Id
563 * @type: Error type. Please see enum vxge_hw_event{}
564 *
565 * Handle error.
566 */
567enum vxge_hw_status
568__vxge_hw_device_handle_error(
569		struct __vxge_hw_device *hldev,
570		u32 vp_id,
571		enum vxge_hw_event type)
572{
573	switch (type) {
574	case VXGE_HW_EVENT_UNKNOWN:
575		break;
576	case VXGE_HW_EVENT_RESET_START:
577	case VXGE_HW_EVENT_RESET_COMPLETE:
578	case VXGE_HW_EVENT_LINK_DOWN:
579	case VXGE_HW_EVENT_LINK_UP:
580		goto out;
581	case VXGE_HW_EVENT_ALARM_CLEARED:
582		goto out;
583	case VXGE_HW_EVENT_ECCERR:
584	case VXGE_HW_EVENT_MRPCIM_ECCERR:
585		goto out;
586	case VXGE_HW_EVENT_FIFO_ERR:
587	case VXGE_HW_EVENT_VPATH_ERR:
588	case VXGE_HW_EVENT_CRITICAL_ERR:
589	case VXGE_HW_EVENT_SERR:
590		break;
591	case VXGE_HW_EVENT_SRPCIM_SERR:
592	case VXGE_HW_EVENT_MRPCIM_SERR:
593		goto out;
594	case VXGE_HW_EVENT_SLOT_FREEZE:
595		break;
596	default:
597		vxge_assert(0);
598		goto out;
599	}
600
601	/* notify driver */
602	if (hldev->uld_callbacks.crit_err)
603		hldev->uld_callbacks.crit_err(
604			(struct __vxge_hw_device *)hldev,
605			type, vp_id);
606out:
607
608	return VXGE_HW_OK;
609}
610
611/**
612 * vxge_hw_device_clear_tx_rx - Acknowledge (that is, clear) the
613 * condition that has caused the Tx and RX interrupt.
614 * @hldev: HW device.
615 *
616 * Acknowledge (that is, clear) the condition that has caused
617 * the Tx and Rx interrupt.
618 * See also: vxge_hw_device_begin_irq(),
619 * vxge_hw_device_mask_tx_rx(), vxge_hw_device_unmask_tx_rx().
620 */
621void vxge_hw_device_clear_tx_rx(struct __vxge_hw_device *hldev)
622{
623
624	if ((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
625	   (hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
626		writeq((hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
627				 hldev->tim_int_mask0[VXGE_HW_VPATH_INTR_RX]),
628				&hldev->common_reg->tim_int_status0);
629	}
630
631	if ((hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
632	   (hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
633		__vxge_hw_pio_mem_write32_upper(
634				(hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
635				 hldev->tim_int_mask1[VXGE_HW_VPATH_INTR_RX]),
636				&hldev->common_reg->tim_int_status1);
637	}
638}
639
640/*
641 * vxge_hw_channel_dtr_alloc - Allocate a dtr from the channel
642 * @channel: Channel
643 * @dtrh: Buffer to return the DTR pointer
644 *
645 * Allocates a dtr from the reserve array. If the reserve array is empty,
646 * it swaps the reserve and free arrays.
647 *
648 */
649enum vxge_hw_status
650vxge_hw_channel_dtr_alloc(struct __vxge_hw_channel *channel, void **dtrh)
651{
652	void **tmp_arr;
653
654	if (channel->reserve_ptr - channel->reserve_top > 0) {
655_alloc_after_swap:
656		*dtrh =	channel->reserve_arr[--channel->reserve_ptr];
657
658		return VXGE_HW_OK;
659	}
660
661	/* switch between empty	and full arrays	*/
662
663	/* the idea behind such	a design is that by having free	and reserved
664	 * arrays separated we basically separated irq and non-irq parts.
665	 * i.e.	no additional lock need	to be done when	we free	a resource */
666
667	if (channel->length - channel->free_ptr > 0) {
668
669		tmp_arr	= channel->reserve_arr;
670		channel->reserve_arr = channel->free_arr;
671		channel->free_arr = tmp_arr;
672		channel->reserve_ptr = channel->length;
673		channel->reserve_top = channel->free_ptr;
674		channel->free_ptr = channel->length;
675
676		channel->stats->reserve_free_swaps_cnt++;
677
678		goto _alloc_after_swap;
679	}
680
681	channel->stats->full_cnt++;
682
683	*dtrh =	NULL;
684	return VXGE_HW_INF_OUT_OF_DESCRIPTORS;
685}
686
687/*
688 * vxge_hw_channel_dtr_post - Post a dtr to the channel
689 * @channelh: Channel
690 * @dtrh: DTR pointer
691 *
692 * Posts a dtr to work array.
693 *
694 */
695void vxge_hw_channel_dtr_post(struct __vxge_hw_channel *channel, void *dtrh)
696{
697	vxge_assert(channel->work_arr[channel->post_index] == NULL);
698
699	channel->work_arr[channel->post_index++] = dtrh;
700
701	/* wrap-around */
702	if (channel->post_index	== channel->length)
703		channel->post_index = 0;
704}
705
706/*
707 * vxge_hw_channel_dtr_try_complete - Returns next completed dtr
708 * @channel: Channel
709 * @dtr: Buffer to return the next completed DTR pointer
710 *
711 * Returns the next completed dtr with out removing it from work array
712 *
713 */
714void
715vxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel, void **dtrh)
716{
717	vxge_assert(channel->compl_index < channel->length);
718
719	*dtrh =	channel->work_arr[channel->compl_index];
720	prefetch(*dtrh);
721}
722
723/*
724 * vxge_hw_channel_dtr_complete - Removes next completed dtr from the work array
725 * @channel: Channel handle
726 *
727 * Removes the next completed dtr from work array
728 *
729 */
730void vxge_hw_channel_dtr_complete(struct __vxge_hw_channel *channel)
731{
732	channel->work_arr[channel->compl_index]	= NULL;
733
734	/* wrap-around */
735	if (++channel->compl_index == channel->length)
736		channel->compl_index = 0;
737
738	channel->stats->total_compl_cnt++;
739}
740
741/*
742 * vxge_hw_channel_dtr_free - Frees a dtr
743 * @channel: Channel handle
744 * @dtr:  DTR pointer
745 *
746 * Returns the dtr to free array
747 *
748 */
749void vxge_hw_channel_dtr_free(struct __vxge_hw_channel *channel, void *dtrh)
750{
751	channel->free_arr[--channel->free_ptr] = dtrh;
752}
753
754/*
755 * vxge_hw_channel_dtr_count
756 * @channel: Channel handle. Obtained via vxge_hw_channel_open().
757 *
758 * Retreive number of DTRs available. This function can not be called
759 * from data path. ring_initial_replenishi() is the only user.
760 */
761int vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel)
762{
763	return (channel->reserve_ptr - channel->reserve_top) +
764		(channel->length - channel->free_ptr);
765}
766
767/**
768 * vxge_hw_ring_rxd_reserve	- Reserve ring descriptor.
769 * @ring: Handle to the ring object used for receive
770 * @rxdh: Reserved descriptor. On success HW fills this "out" parameter
771 * with a valid handle.
772 *
773 * Reserve Rx descriptor for the subsequent filling-in driver
774 * and posting on the corresponding channel (@channelh)
775 * via vxge_hw_ring_rxd_post().
776 *
777 * Returns: VXGE_HW_OK - success.
778 * VXGE_HW_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available.
779 *
780 */
781enum vxge_hw_status vxge_hw_ring_rxd_reserve(struct __vxge_hw_ring *ring,
782	void **rxdh)
783{
784	enum vxge_hw_status status;
785	struct __vxge_hw_channel *channel;
786
787	channel = &ring->channel;
788
789	status = vxge_hw_channel_dtr_alloc(channel, rxdh);
790
791	if (status == VXGE_HW_OK) {
792		struct vxge_hw_ring_rxd_1 *rxdp =
793			(struct vxge_hw_ring_rxd_1 *)*rxdh;
794
795		rxdp->control_0	= rxdp->control_1 = 0;
796	}
797
798	return status;
799}
800
801/**
802 * vxge_hw_ring_rxd_free - Free descriptor.
803 * @ring: Handle to the ring object used for receive
804 * @rxdh: Descriptor handle.
805 *
806 * Free	the reserved descriptor. This operation is "symmetrical" to
807 * vxge_hw_ring_rxd_reserve. The "free-ing" completes the descriptor's
808 * lifecycle.
809 *
810 * After free-ing (see vxge_hw_ring_rxd_free()) the descriptor again can
811 * be:
812 *
813 * - reserved (vxge_hw_ring_rxd_reserve);
814 *
815 * - posted	(vxge_hw_ring_rxd_post);
816 *
817 * - completed (vxge_hw_ring_rxd_next_completed);
818 *
819 * - and recycled again	(vxge_hw_ring_rxd_free).
820 *
821 * For alternative state transitions and more details please refer to
822 * the design doc.
823 *
824 */
825void vxge_hw_ring_rxd_free(struct __vxge_hw_ring *ring, void *rxdh)
826{
827	struct __vxge_hw_channel *channel;
828
829	channel = &ring->channel;
830
831	vxge_hw_channel_dtr_free(channel, rxdh);
832
833}
834
835/**
836 * vxge_hw_ring_rxd_pre_post - Prepare rxd and post
837 * @ring: Handle to the ring object used for receive
838 * @rxdh: Descriptor handle.
839 *
840 * This routine prepares a rxd and posts
841 */
842void vxge_hw_ring_rxd_pre_post(struct __vxge_hw_ring *ring, void *rxdh)
843{
844	struct __vxge_hw_channel *channel;
845
846	channel = &ring->channel;
847
848	vxge_hw_channel_dtr_post(channel, rxdh);
849}
850
851/**
852 * vxge_hw_ring_rxd_post_post - Process rxd after post.
853 * @ring: Handle to the ring object used for receive
854 * @rxdh: Descriptor handle.
855 *
856 * Processes rxd after post
857 */
858void vxge_hw_ring_rxd_post_post(struct __vxge_hw_ring *ring, void *rxdh)
859{
860	struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh;
861	struct __vxge_hw_channel *channel;
862
863	channel = &ring->channel;
864
865	rxdp->control_0	= VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
866
867	if (ring->stats->common_stats.usage_cnt > 0)
868		ring->stats->common_stats.usage_cnt--;
869}
870
871/**
872 * vxge_hw_ring_rxd_post - Post descriptor on the ring.
873 * @ring: Handle to the ring object used for receive
874 * @rxdh: Descriptor obtained via vxge_hw_ring_rxd_reserve().
875 *
876 * Post	descriptor on the ring.
877 * Prior to posting the	descriptor should be filled in accordance with
878 * Host/Titan interface specification for a given service (LL, etc.).
879 *
880 */
881void vxge_hw_ring_rxd_post(struct __vxge_hw_ring *ring, void *rxdh)
882{
883	struct vxge_hw_ring_rxd_1 *rxdp = (struct vxge_hw_ring_rxd_1 *)rxdh;
884	struct __vxge_hw_channel *channel;
885
886	channel = &ring->channel;
887
888	wmb();
889	rxdp->control_0	= VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
890
891	vxge_hw_channel_dtr_post(channel, rxdh);
892
893	if (ring->stats->common_stats.usage_cnt > 0)
894		ring->stats->common_stats.usage_cnt--;
895}
896
897/**
898 * vxge_hw_ring_rxd_post_post_wmb - Process rxd after post with memory barrier.
899 * @ring: Handle to the ring object used for receive
900 * @rxdh: Descriptor handle.
901 *
902 * Processes rxd after post with memory barrier.
903 */
904void vxge_hw_ring_rxd_post_post_wmb(struct __vxge_hw_ring *ring, void *rxdh)
905{
906	struct __vxge_hw_channel *channel;
907
908	channel = &ring->channel;
909
910	wmb();
911	vxge_hw_ring_rxd_post_post(ring, rxdh);
912}
913
914/**
915 * vxge_hw_ring_rxd_next_completed - Get the _next_ completed descriptor.
916 * @ring: Handle to the ring object used for receive
917 * @rxdh: Descriptor handle. Returned by HW.
918 * @t_code:	Transfer code, as per Titan User Guide,
919 *	 Receive Descriptor Format. Returned by HW.
920 *
921 * Retrieve the	_next_ completed descriptor.
922 * HW uses ring callback (*vxge_hw_ring_callback_f) to notifiy
923 * driver of new completed descriptors. After that
924 * the driver can use vxge_hw_ring_rxd_next_completed to retrieve the rest
925 * completions (the very first completion is passed by HW via
926 * vxge_hw_ring_callback_f).
927 *
928 * Implementation-wise, the driver is free to call
929 * vxge_hw_ring_rxd_next_completed either immediately from inside the
930 * ring callback, or in a deferred fashion and separate (from HW)
931 * context.
932 *
933 * Non-zero @t_code means failure to fill-in receive buffer(s)
934 * of the descriptor.
935 * For instance, parity	error detected during the data transfer.
936 * In this case	Titan will complete the descriptor and indicate
937 * for the host	that the received data is not to be used.
938 * For details please refer to Titan User Guide.
939 *
940 * Returns: VXGE_HW_OK - success.
941 * VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
942 * are currently available for processing.
943 *
944 * See also: vxge_hw_ring_callback_f{},
945 * vxge_hw_fifo_rxd_next_completed(), enum vxge_hw_status{}.
946 */
947enum vxge_hw_status vxge_hw_ring_rxd_next_completed(
948	struct __vxge_hw_ring *ring, void **rxdh, u8 *t_code)
949{
950	struct __vxge_hw_channel *channel;
951	struct vxge_hw_ring_rxd_1 *rxdp;
952	enum vxge_hw_status status = VXGE_HW_OK;
953	u64 control_0, own;
954
955	channel = &ring->channel;
956
957	vxge_hw_channel_dtr_try_complete(channel, rxdh);
958
959	rxdp = (struct vxge_hw_ring_rxd_1 *)*rxdh;
960	if (rxdp == NULL) {
961		status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
962		goto exit;
963	}
964
965	control_0 = rxdp->control_0;
966	own = control_0 & VXGE_HW_RING_RXD_LIST_OWN_ADAPTER;
967	*t_code	= (u8)VXGE_HW_RING_RXD_T_CODE_GET(control_0);
968
969	/* check whether it is not the end */
970	if (!own || ((*t_code == VXGE_HW_RING_T_CODE_FRM_DROP) && own)) {
971
972		vxge_assert(((struct vxge_hw_ring_rxd_1 *)rxdp)->host_control !=
973				0);
974
975		++ring->cmpl_cnt;
976		vxge_hw_channel_dtr_complete(channel);
977
978		vxge_assert(*t_code != VXGE_HW_RING_RXD_T_CODE_UNUSED);
979
980		ring->stats->common_stats.usage_cnt++;
981		if (ring->stats->common_stats.usage_max <
982				ring->stats->common_stats.usage_cnt)
983			ring->stats->common_stats.usage_max =
984				ring->stats->common_stats.usage_cnt;
985
986		status = VXGE_HW_OK;
987		goto exit;
988	}
989
990	/* reset it. since we don't want to return
991	 * garbage to the driver */
992	*rxdh =	NULL;
993	status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
994exit:
995	return status;
996}
997
998/**
999 * vxge_hw_ring_handle_tcode - Handle transfer code.
1000 * @ring: Handle to the ring object used for receive
1001 * @rxdh: Descriptor handle.
1002 * @t_code: One of the enumerated (and documented in the Titan user guide)
1003 * "transfer codes".
1004 *
1005 * Handle descriptor's transfer code. The latter comes with each completed
1006 * descriptor.
1007 *
1008 * Returns: one of the enum vxge_hw_status{} enumerated types.
1009 * VXGE_HW_OK			- for success.
1010 * VXGE_HW_ERR_CRITICAL         - when encounters critical error.
1011 */
1012enum vxge_hw_status vxge_hw_ring_handle_tcode(
1013	struct __vxge_hw_ring *ring, void *rxdh, u8 t_code)
1014{
1015	struct __vxge_hw_channel *channel;
1016	enum vxge_hw_status status = VXGE_HW_OK;
1017
1018	channel = &ring->channel;
1019
1020	/* If the t_code is not supported and if the
1021	 * t_code is other than 0x5 (unparseable packet
1022	 * such as unknown UPV6 header), Drop it !!!
1023	 */
1024
1025	if (t_code ==  VXGE_HW_RING_T_CODE_OK ||
1026		t_code == VXGE_HW_RING_T_CODE_L3_PKT_ERR) {
1027		status = VXGE_HW_OK;
1028		goto exit;
1029	}
1030
1031	if (t_code > VXGE_HW_RING_T_CODE_MULTI_ERR) {
1032		status = VXGE_HW_ERR_INVALID_TCODE;
1033		goto exit;
1034	}
1035
1036	ring->stats->rxd_t_code_err_cnt[t_code]++;
1037exit:
1038	return status;
1039}
1040
1041/**
1042 * __vxge_hw_non_offload_db_post - Post non offload doorbell
1043 *
1044 * @fifo: fifohandle
1045 * @txdl_ptr: The starting location of the TxDL in host memory
1046 * @num_txds: The highest TxD in this TxDL (0 to 255 means 1 to 256)
1047 * @no_snoop: No snoop flags
1048 *
1049 * This function posts a non-offload doorbell to doorbell FIFO
1050 *
1051 */
1052static void __vxge_hw_non_offload_db_post(struct __vxge_hw_fifo *fifo,
1053	u64 txdl_ptr, u32 num_txds, u32 no_snoop)
1054{
1055	struct __vxge_hw_channel *channel;
1056
1057	channel = &fifo->channel;
1058
1059	writeq(VXGE_HW_NODBW_TYPE(VXGE_HW_NODBW_TYPE_NODBW) |
1060		VXGE_HW_NODBW_LAST_TXD_NUMBER(num_txds) |
1061		VXGE_HW_NODBW_GET_NO_SNOOP(no_snoop),
1062		&fifo->nofl_db->control_0);
1063
1064	mmiowb();
1065
1066	writeq(txdl_ptr, &fifo->nofl_db->txdl_ptr);
1067
1068	mmiowb();
1069}
1070
1071/**
1072 * vxge_hw_fifo_free_txdl_count_get - returns the number of txdls available in
1073 * the fifo
1074 * @fifoh: Handle to the fifo object used for non offload send
1075 */
1076u32 vxge_hw_fifo_free_txdl_count_get(struct __vxge_hw_fifo *fifoh)
1077{
1078	return vxge_hw_channel_dtr_count(&fifoh->channel);
1079}
1080
1081/**
1082 * vxge_hw_fifo_txdl_reserve - Reserve fifo descriptor.
1083 * @fifoh: Handle to the fifo object used for non offload send
1084 * @txdlh: Reserved descriptor. On success HW fills this "out" parameter
1085 *        with a valid handle.
1086 * @txdl_priv: Buffer to return the pointer to per txdl space
1087 *
1088 * Reserve a single TxDL (that is, fifo descriptor)
1089 * for the subsequent filling-in by driver)
1090 * and posting on the corresponding channel (@channelh)
1091 * via vxge_hw_fifo_txdl_post().
1092 *
1093 * Note: it is the responsibility of driver to reserve multiple descriptors
1094 * for lengthy (e.g., LSO) transmit operation. A single fifo descriptor
1095 * carries up to configured number (fifo.max_frags) of contiguous buffers.
1096 *
1097 * Returns: VXGE_HW_OK - success;
1098 * VXGE_HW_INF_OUT_OF_DESCRIPTORS - Currently no descriptors available
1099 *
1100 */
1101enum vxge_hw_status vxge_hw_fifo_txdl_reserve(
1102	struct __vxge_hw_fifo *fifo,
1103	void **txdlh, void **txdl_priv)
1104{
1105	struct __vxge_hw_channel *channel;
1106	enum vxge_hw_status status;
1107	int i;
1108
1109	channel = &fifo->channel;
1110
1111	status = vxge_hw_channel_dtr_alloc(channel, txdlh);
1112
1113	if (status == VXGE_HW_OK) {
1114		struct vxge_hw_fifo_txd *txdp =
1115			(struct vxge_hw_fifo_txd *)*txdlh;
1116		struct __vxge_hw_fifo_txdl_priv *priv;
1117
1118		priv = __vxge_hw_fifo_txdl_priv(fifo, txdp);
1119
1120		/* reset the TxDL's private */
1121		priv->align_dma_offset = 0;
1122		priv->align_vaddr_start = priv->align_vaddr;
1123		priv->align_used_frags = 0;
1124		priv->frags = 0;
1125		priv->alloc_frags = fifo->config->max_frags;
1126		priv->next_txdl_priv = NULL;
1127
1128		*txdl_priv = (void *)(size_t)txdp->host_control;
1129
1130		for (i = 0; i < fifo->config->max_frags; i++) {
1131			txdp = ((struct vxge_hw_fifo_txd *)*txdlh) + i;
1132			txdp->control_0 = txdp->control_1 = 0;
1133		}
1134	}
1135
1136	return status;
1137}
1138
1139/**
1140 * vxge_hw_fifo_txdl_buffer_set - Set transmit buffer pointer in the
1141 * descriptor.
1142 * @fifo: Handle to the fifo object used for non offload send
1143 * @txdlh: Descriptor handle.
1144 * @frag_idx: Index of the data buffer in the caller's scatter-gather list
1145 *            (of buffers).
1146 * @dma_pointer: DMA address of the data buffer referenced by @frag_idx.
1147 * @size: Size of the data buffer (in bytes).
1148 *
1149 * This API is part of the preparation of the transmit descriptor for posting
1150 * (via vxge_hw_fifo_txdl_post()). The related "preparation" APIs include
1151 * vxge_hw_fifo_txdl_mss_set() and vxge_hw_fifo_txdl_cksum_set_bits().
1152 * All three APIs fill in the fields of the fifo descriptor,
1153 * in accordance with the Titan specification.
1154 *
1155 */
1156void vxge_hw_fifo_txdl_buffer_set(struct __vxge_hw_fifo *fifo,
1157				  void *txdlh, u32 frag_idx,
1158				  dma_addr_t dma_pointer, u32 size)
1159{
1160	struct __vxge_hw_fifo_txdl_priv *txdl_priv;
1161	struct vxge_hw_fifo_txd *txdp, *txdp_last;
1162	struct __vxge_hw_channel *channel;
1163
1164	channel = &fifo->channel;
1165
1166	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
1167	txdp = (struct vxge_hw_fifo_txd *)txdlh  +  txdl_priv->frags;
1168
1169	if (frag_idx != 0)
1170		txdp->control_0 = txdp->control_1 = 0;
1171	else {
1172		txdp->control_0 |= VXGE_HW_FIFO_TXD_GATHER_CODE(
1173			VXGE_HW_FIFO_TXD_GATHER_CODE_FIRST);
1174		txdp->control_1 |= fifo->interrupt_type;
1175		txdp->control_1 |= VXGE_HW_FIFO_TXD_INT_NUMBER(
1176			fifo->tx_intr_num);
1177		if (txdl_priv->frags) {
1178			txdp_last = (struct vxge_hw_fifo_txd *)txdlh  +
1179			(txdl_priv->frags - 1);
1180			txdp_last->control_0 |= VXGE_HW_FIFO_TXD_GATHER_CODE(
1181				VXGE_HW_FIFO_TXD_GATHER_CODE_LAST);
1182		}
1183	}
1184
1185	vxge_assert(frag_idx < txdl_priv->alloc_frags);
1186
1187	txdp->buffer_pointer = (u64)dma_pointer;
1188	txdp->control_0 |= VXGE_HW_FIFO_TXD_BUFFER_SIZE(size);
1189	fifo->stats->total_buffers++;
1190	txdl_priv->frags++;
1191}
1192
1193/**
1194 * vxge_hw_fifo_txdl_post - Post descriptor on the fifo channel.
1195 * @fifo: Handle to the fifo object used for non offload send
1196 * @txdlh: Descriptor obtained via vxge_hw_fifo_txdl_reserve()
1197 * @frags: Number of contiguous buffers that are part of a single
1198 *         transmit operation.
1199 *
1200 * Post descriptor on the 'fifo' type channel for transmission.
1201 * Prior to posting the descriptor should be filled in accordance with
1202 * Host/Titan interface specification for a given service (LL, etc.).
1203 *
1204 */
1205void vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo, void *txdlh)
1206{
1207	struct __vxge_hw_fifo_txdl_priv *txdl_priv;
1208	struct vxge_hw_fifo_txd *txdp_last;
1209	struct vxge_hw_fifo_txd *txdp_first;
1210	struct __vxge_hw_channel *channel;
1211
1212	channel = &fifo->channel;
1213
1214	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo, txdlh);
1215	txdp_first = (struct vxge_hw_fifo_txd *)txdlh;
1216
1217	txdp_last = (struct vxge_hw_fifo_txd *)txdlh  +  (txdl_priv->frags - 1);
1218	txdp_last->control_0 |=
1219	      VXGE_HW_FIFO_TXD_GATHER_CODE(VXGE_HW_FIFO_TXD_GATHER_CODE_LAST);
1220	txdp_first->control_0 |= VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER;
1221
1222	vxge_hw_channel_dtr_post(&fifo->channel, txdlh);
1223
1224	__vxge_hw_non_offload_db_post(fifo,
1225		(u64)txdl_priv->dma_addr,
1226		txdl_priv->frags - 1,
1227		fifo->no_snoop_bits);
1228
1229	fifo->stats->total_posts++;
1230	fifo->stats->common_stats.usage_cnt++;
1231	if (fifo->stats->common_stats.usage_max <
1232		fifo->stats->common_stats.usage_cnt)
1233		fifo->stats->common_stats.usage_max =
1234			fifo->stats->common_stats.usage_cnt;
1235}
1236
1237/**
1238 * vxge_hw_fifo_txdl_next_completed - Retrieve next completed descriptor.
1239 * @fifo: Handle to the fifo object used for non offload send
1240 * @txdlh: Descriptor handle. Returned by HW.
1241 * @t_code: Transfer code, as per Titan User Guide,
1242 *          Transmit Descriptor Format.
1243 *          Returned by HW.
1244 *
1245 * Retrieve the _next_ completed descriptor.
1246 * HW uses channel callback (*vxge_hw_channel_callback_f) to notifiy
1247 * driver of new completed descriptors. After that
1248 * the driver can use vxge_hw_fifo_txdl_next_completed to retrieve the rest
1249 * completions (the very first completion is passed by HW via
1250 * vxge_hw_channel_callback_f).
1251 *
1252 * Implementation-wise, the driver is free to call
1253 * vxge_hw_fifo_txdl_next_completed either immediately from inside the
1254 * channel callback, or in a deferred fashion and separate (from HW)
1255 * context.
1256 *
1257 * Non-zero @t_code means failure to process the descriptor.
1258 * The failure could happen, for instance, when the link is
1259 * down, in which case Titan completes the descriptor because it
1260 * is not able to send the data out.
1261 *
1262 * For details please refer to Titan User Guide.
1263 *
1264 * Returns: VXGE_HW_OK - success.
1265 * VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS - No completed descriptors
1266 * are currently available for processing.
1267 *
1268 */
1269enum vxge_hw_status vxge_hw_fifo_txdl_next_completed(
1270	struct __vxge_hw_fifo *fifo, void **txdlh,
1271	enum vxge_hw_fifo_tcode *t_code)
1272{
1273	struct __vxge_hw_channel *channel;
1274	struct vxge_hw_fifo_txd *txdp;
1275	enum vxge_hw_status status = VXGE_HW_OK;
1276
1277	channel = &fifo->channel;
1278
1279	vxge_hw_channel_dtr_try_complete(channel, txdlh);
1280
1281	txdp = (struct vxge_hw_fifo_txd *)*txdlh;
1282	if (txdp == NULL) {
1283		status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1284		goto exit;
1285	}
1286
1287	/* check whether host owns it */
1288	if (!(txdp->control_0 & VXGE_HW_FIFO_TXD_LIST_OWN_ADAPTER)) {
1289
1290		vxge_assert(txdp->host_control != 0);
1291
1292		vxge_hw_channel_dtr_complete(channel);
1293
1294		*t_code = (u8)VXGE_HW_FIFO_TXD_T_CODE_GET(txdp->control_0);
1295
1296		if (fifo->stats->common_stats.usage_cnt > 0)
1297			fifo->stats->common_stats.usage_cnt--;
1298
1299		status = VXGE_HW_OK;
1300		goto exit;
1301	}
1302
1303	/* no more completions */
1304	*txdlh = NULL;
1305	status = VXGE_HW_INF_NO_MORE_COMPLETED_DESCRIPTORS;
1306exit:
1307	return status;
1308}
1309
1310/**
1311 * vxge_hw_fifo_handle_tcode - Handle transfer code.
1312 * @fifo: Handle to the fifo object used for non offload send
1313 * @txdlh: Descriptor handle.
1314 * @t_code: One of the enumerated (and documented in the Titan user guide)
1315 *          "transfer codes".
1316 *
1317 * Handle descriptor's transfer code. The latter comes with each completed
1318 * descriptor.
1319 *
1320 * Returns: one of the enum vxge_hw_status{} enumerated types.
1321 * VXGE_HW_OK - for success.
1322 * VXGE_HW_ERR_CRITICAL - when encounters critical error.
1323 */
1324enum vxge_hw_status vxge_hw_fifo_handle_tcode(struct __vxge_hw_fifo *fifo,
1325					      void *txdlh,
1326					      enum vxge_hw_fifo_tcode t_code)
1327{
1328	struct __vxge_hw_channel *channel;
1329
1330	enum vxge_hw_status status = VXGE_HW_OK;
1331	channel = &fifo->channel;
1332
1333	if (((t_code & 0x7) < 0) || ((t_code & 0x7) > 0x4)) {
1334		status = VXGE_HW_ERR_INVALID_TCODE;
1335		goto exit;
1336	}
1337
1338	fifo->stats->txd_t_code_err_cnt[t_code]++;
1339exit:
1340	return status;
1341}
1342
1343/**
1344 * vxge_hw_fifo_txdl_free - Free descriptor.
1345 * @fifo: Handle to the fifo object used for non offload send
1346 * @txdlh: Descriptor handle.
1347 *
1348 * Free the reserved descriptor. This operation is "symmetrical" to
1349 * vxge_hw_fifo_txdl_reserve. The "free-ing" completes the descriptor's
1350 * lifecycle.
1351 *
1352 * After free-ing (see vxge_hw_fifo_txdl_free()) the descriptor again can
1353 * be:
1354 *
1355 * - reserved (vxge_hw_fifo_txdl_reserve);
1356 *
1357 * - posted (vxge_hw_fifo_txdl_post);
1358 *
1359 * - completed (vxge_hw_fifo_txdl_next_completed);
1360 *
1361 * - and recycled again (vxge_hw_fifo_txdl_free).
1362 *
1363 * For alternative state transitions and more details please refer to
1364 * the design doc.
1365 *
1366 */
1367void vxge_hw_fifo_txdl_free(struct __vxge_hw_fifo *fifo, void *txdlh)
1368{
1369	struct __vxge_hw_fifo_txdl_priv *txdl_priv;
1370	u32 max_frags;
1371	struct __vxge_hw_channel *channel;
1372
1373	channel = &fifo->channel;
1374
1375	txdl_priv = __vxge_hw_fifo_txdl_priv(fifo,
1376			(struct vxge_hw_fifo_txd *)txdlh);
1377
1378	max_frags = fifo->config->max_frags;
1379
1380	vxge_hw_channel_dtr_free(channel, txdlh);
1381}
1382
1383/**
1384 * vxge_hw_vpath_mac_addr_add - Add the mac address entry for this vpath
1385 *               to MAC address table.
1386 * @vp: Vpath handle.
1387 * @macaddr: MAC address to be added for this vpath into the list
1388 * @macaddr_mask: MAC address mask for macaddr
1389 * @duplicate_mode: Duplicate MAC address add mode. Please see
1390 *             enum vxge_hw_vpath_mac_addr_add_mode{}
1391 *
1392 * Adds the given mac address and mac address mask into the list for this
1393 * vpath.
1394 * see also: vxge_hw_vpath_mac_addr_delete, vxge_hw_vpath_mac_addr_get and
1395 * vxge_hw_vpath_mac_addr_get_next
1396 *
1397 */
1398enum vxge_hw_status
1399vxge_hw_vpath_mac_addr_add(
1400	struct __vxge_hw_vpath_handle *vp,
1401	u8 (macaddr)[ETH_ALEN],
1402	u8 (macaddr_mask)[ETH_ALEN],
1403	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode)
1404{
1405	u32 i;
1406	u64 data1 = 0ULL;
1407	u64 data2 = 0ULL;
1408	enum vxge_hw_status status = VXGE_HW_OK;
1409
1410	if (vp == NULL) {
1411		status = VXGE_HW_ERR_INVALID_HANDLE;
1412		goto exit;
1413	}
1414
1415	for (i = 0; i < ETH_ALEN; i++) {
1416		data1 <<= 8;
1417		data1 |= (u8)macaddr[i];
1418
1419		data2 <<= 8;
1420		data2 |= (u8)macaddr_mask[i];
1421	}
1422
1423	switch (duplicate_mode) {
1424	case VXGE_HW_VPATH_MAC_ADDR_ADD_DUPLICATE:
1425		i = 0;
1426		break;
1427	case VXGE_HW_VPATH_MAC_ADDR_DISCARD_DUPLICATE:
1428		i = 1;
1429		break;
1430	case VXGE_HW_VPATH_MAC_ADDR_REPLACE_DUPLICATE:
1431		i = 2;
1432		break;
1433	default:
1434		i = 0;
1435		break;
1436	}
1437
1438	status = __vxge_hw_vpath_rts_table_set(vp,
1439			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY,
1440			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
1441			0,
1442			VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR(data1),
1443			VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK(data2)|
1444			VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MODE(i));
1445exit:
1446	return status;
1447}
1448
1449/**
1450 * vxge_hw_vpath_mac_addr_get - Get the first mac address entry for this vpath
1451 *               from MAC address table.
1452 * @vp: Vpath handle.
1453 * @macaddr: First MAC address entry for this vpath in the list
1454 * @macaddr_mask: MAC address mask for macaddr
1455 *
1456 * Returns the first mac address and mac address mask in the list for this
1457 * vpath.
1458 * see also: vxge_hw_vpath_mac_addr_get_next
1459 *
1460 */
1461enum vxge_hw_status
1462vxge_hw_vpath_mac_addr_get(
1463	struct __vxge_hw_vpath_handle *vp,
1464	u8 (macaddr)[ETH_ALEN],
1465	u8 (macaddr_mask)[ETH_ALEN])
1466{
1467	u32 i;
1468	u64 data1 = 0ULL;
1469	u64 data2 = 0ULL;
1470	enum vxge_hw_status status = VXGE_HW_OK;
1471
1472	if (vp == NULL) {
1473		status = VXGE_HW_ERR_INVALID_HANDLE;
1474		goto exit;
1475	}
1476
1477	status = __vxge_hw_vpath_rts_table_get(vp,
1478			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY,
1479			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
1480			0, &data1, &data2);
1481
1482	if (status != VXGE_HW_OK)
1483		goto exit;
1484
1485	data1 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1);
1486
1487	data2 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(data2);
1488
1489	for (i = ETH_ALEN; i > 0; i--) {
1490		macaddr[i-1] = (u8)(data1 & 0xFF);
1491		data1 >>= 8;
1492
1493		macaddr_mask[i-1] = (u8)(data2 & 0xFF);
1494		data2 >>= 8;
1495	}
1496exit:
1497	return status;
1498}
1499
1500/**
1501 * vxge_hw_vpath_mac_addr_get_next - Get the next mac address entry for this
1502 * vpath
1503 *               from MAC address table.
1504 * @vp: Vpath handle.
1505 * @macaddr: Next MAC address entry for this vpath in the list
1506 * @macaddr_mask: MAC address mask for macaddr
1507 *
1508 * Returns the next mac address and mac address mask in the list for this
1509 * vpath.
1510 * see also: vxge_hw_vpath_mac_addr_get
1511 *
1512 */
1513enum vxge_hw_status
1514vxge_hw_vpath_mac_addr_get_next(
1515	struct __vxge_hw_vpath_handle *vp,
1516	u8 (macaddr)[ETH_ALEN],
1517	u8 (macaddr_mask)[ETH_ALEN])
1518{
1519	u32 i;
1520	u64 data1 = 0ULL;
1521	u64 data2 = 0ULL;
1522	enum vxge_hw_status status = VXGE_HW_OK;
1523
1524	if (vp == NULL) {
1525		status = VXGE_HW_ERR_INVALID_HANDLE;
1526		goto exit;
1527	}
1528
1529	status = __vxge_hw_vpath_rts_table_get(vp,
1530			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY,
1531			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
1532			0, &data1, &data2);
1533
1534	if (status != VXGE_HW_OK)
1535		goto exit;
1536
1537	data1 = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_DA_MAC_ADDR(data1);
1538
1539	data2 = VXGE_HW_RTS_ACCESS_STEER_DATA1_GET_DA_MAC_ADDR_MASK(data2);
1540
1541	for (i = ETH_ALEN; i > 0; i--) {
1542		macaddr[i-1] = (u8)(data1 & 0xFF);
1543		data1 >>= 8;
1544
1545		macaddr_mask[i-1] = (u8)(data2 & 0xFF);
1546		data2 >>= 8;
1547	}
1548
1549exit:
1550	return status;
1551}
1552
1553/**
1554 * vxge_hw_vpath_mac_addr_delete - Delete the mac address entry for this vpath
1555 *               to MAC address table.
1556 * @vp: Vpath handle.
1557 * @macaddr: MAC address to be added for this vpath into the list
1558 * @macaddr_mask: MAC address mask for macaddr
1559 *
1560 * Delete the given mac address and mac address mask into the list for this
1561 * vpath.
1562 * see also: vxge_hw_vpath_mac_addr_add, vxge_hw_vpath_mac_addr_get and
1563 * vxge_hw_vpath_mac_addr_get_next
1564 *
1565 */
1566enum vxge_hw_status
1567vxge_hw_vpath_mac_addr_delete(
1568	struct __vxge_hw_vpath_handle *vp,
1569	u8 (macaddr)[ETH_ALEN],
1570	u8 (macaddr_mask)[ETH_ALEN])
1571{
1572	u32 i;
1573	u64 data1 = 0ULL;
1574	u64 data2 = 0ULL;
1575	enum vxge_hw_status status = VXGE_HW_OK;
1576
1577	if (vp == NULL) {
1578		status = VXGE_HW_ERR_INVALID_HANDLE;
1579		goto exit;
1580	}
1581
1582	for (i = 0; i < ETH_ALEN; i++) {
1583		data1 <<= 8;
1584		data1 |= (u8)macaddr[i];
1585
1586		data2 <<= 8;
1587		data2 |= (u8)macaddr_mask[i];
1588	}
1589
1590	status = __vxge_hw_vpath_rts_table_set(vp,
1591			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY,
1592			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_DA,
1593			0,
1594			VXGE_HW_RTS_ACCESS_STEER_DATA0_DA_MAC_ADDR(data1),
1595			VXGE_HW_RTS_ACCESS_STEER_DATA1_DA_MAC_ADDR_MASK(data2));
1596exit:
1597	return status;
1598}
1599
1600/**
1601 * vxge_hw_vpath_vid_add - Add the vlan id entry for this vpath
1602 *               to vlan id table.
1603 * @vp: Vpath handle.
1604 * @vid: vlan id to be added for this vpath into the list
1605 *
1606 * Adds the given vlan id into the list for this  vpath.
1607 * see also: vxge_hw_vpath_vid_delete, vxge_hw_vpath_vid_get and
1608 * vxge_hw_vpath_vid_get_next
1609 *
1610 */
1611enum vxge_hw_status
1612vxge_hw_vpath_vid_add(struct __vxge_hw_vpath_handle *vp, u64 vid)
1613{
1614	enum vxge_hw_status status = VXGE_HW_OK;
1615
1616	if (vp == NULL) {
1617		status = VXGE_HW_ERR_INVALID_HANDLE;
1618		goto exit;
1619	}
1620
1621	status = __vxge_hw_vpath_rts_table_set(vp,
1622			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_ADD_ENTRY,
1623			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID,
1624			0, VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID(vid), 0);
1625exit:
1626	return status;
1627}
1628
1629/**
1630 * vxge_hw_vpath_vid_get - Get the first vid entry for this vpath
1631 *               from vlan id table.
1632 * @vp: Vpath handle.
1633 * @vid: Buffer to return vlan id
1634 *
1635 * Returns the first vlan id in the list for this vpath.
1636 * see also: vxge_hw_vpath_vid_get_next
1637 *
1638 */
1639enum vxge_hw_status
1640vxge_hw_vpath_vid_get(struct __vxge_hw_vpath_handle *vp, u64 *vid)
1641{
1642	u64 data;
1643	enum vxge_hw_status status = VXGE_HW_OK;
1644
1645	if (vp == NULL) {
1646		status = VXGE_HW_ERR_INVALID_HANDLE;
1647		goto exit;
1648	}
1649
1650	status = __vxge_hw_vpath_rts_table_get(vp,
1651			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_FIRST_ENTRY,
1652			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID,
1653			0, vid, &data);
1654
1655	*vid = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_VLAN_ID(*vid);
1656exit:
1657	return status;
1658}
1659
1660/**
1661 * vxge_hw_vpath_vid_get_next - Get the next vid entry for this vpath
1662 *               from vlan id table.
1663 * @vp: Vpath handle.
1664 * @vid: Buffer to return vlan id
1665 *
1666 * Returns the next vlan id in the list for this vpath.
1667 * see also: vxge_hw_vpath_vid_get
1668 *
1669 */
1670enum vxge_hw_status
1671vxge_hw_vpath_vid_get_next(struct __vxge_hw_vpath_handle *vp, u64 *vid)
1672{
1673	u64 data;
1674	enum vxge_hw_status status = VXGE_HW_OK;
1675
1676	if (vp == NULL) {
1677		status = VXGE_HW_ERR_INVALID_HANDLE;
1678		goto exit;
1679	}
1680
1681	status = __vxge_hw_vpath_rts_table_get(vp,
1682			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_LIST_NEXT_ENTRY,
1683			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID,
1684			0, vid, &data);
1685
1686	*vid = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_VLAN_ID(*vid);
1687exit:
1688	return status;
1689}
1690
1691/**
1692 * vxge_hw_vpath_vid_delete - Delete the vlan id entry for this vpath
1693 *               to vlan id table.
1694 * @vp: Vpath handle.
1695 * @vid: vlan id to be added for this vpath into the list
1696 *
1697 * Adds the given vlan id into the list for this  vpath.
1698 * see also: vxge_hw_vpath_vid_add, vxge_hw_vpath_vid_get and
1699 * vxge_hw_vpath_vid_get_next
1700 *
1701 */
1702enum vxge_hw_status
1703vxge_hw_vpath_vid_delete(struct __vxge_hw_vpath_handle *vp, u64 vid)
1704{
1705	enum vxge_hw_status status = VXGE_HW_OK;
1706
1707	if (vp == NULL) {
1708		status = VXGE_HW_ERR_INVALID_HANDLE;
1709		goto exit;
1710	}
1711
1712	status = __vxge_hw_vpath_rts_table_set(vp,
1713			VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_DELETE_ENTRY,
1714			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_VID,
1715			0, VXGE_HW_RTS_ACCESS_STEER_DATA0_VLAN_ID(vid), 0);
1716exit:
1717	return status;
1718}
1719
1720/**
1721 * vxge_hw_vpath_promisc_enable - Enable promiscuous mode.
1722 * @vp: Vpath handle.
1723 *
1724 * Enable promiscuous mode of Titan-e operation.
1725 *
1726 * See also: vxge_hw_vpath_promisc_disable().
1727 */
1728enum vxge_hw_status vxge_hw_vpath_promisc_enable(
1729			struct __vxge_hw_vpath_handle *vp)
1730{
1731	u64 val64;
1732	struct __vxge_hw_virtualpath *vpath;
1733	enum vxge_hw_status status = VXGE_HW_OK;
1734
1735	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
1736		status = VXGE_HW_ERR_INVALID_HANDLE;
1737		goto exit;
1738	}
1739
1740	vpath = vp->vpath;
1741
1742	/* Enable promiscous mode for function 0 only */
1743	if (!(vpath->hldev->access_rights &
1744		VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM))
1745		return VXGE_HW_OK;
1746
1747	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
1748
1749	if (!(val64 & VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN)) {
1750
1751		val64 |= VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN |
1752			 VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN |
1753			 VXGE_HW_RXMAC_VCFG0_BCAST_EN |
1754			 VXGE_HW_RXMAC_VCFG0_ALL_VID_EN;
1755
1756		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
1757	}
1758exit:
1759	return status;
1760}
1761
1762/**
1763 * vxge_hw_vpath_promisc_disable - Disable promiscuous mode.
1764 * @vp: Vpath handle.
1765 *
1766 * Disable promiscuous mode of Titan-e operation.
1767 *
1768 * See also: vxge_hw_vpath_promisc_enable().
1769 */
1770enum vxge_hw_status vxge_hw_vpath_promisc_disable(
1771			struct __vxge_hw_vpath_handle *vp)
1772{
1773	u64 val64;
1774	struct __vxge_hw_virtualpath *vpath;
1775	enum vxge_hw_status status = VXGE_HW_OK;
1776
1777	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
1778		status = VXGE_HW_ERR_INVALID_HANDLE;
1779		goto exit;
1780	}
1781
1782	vpath = vp->vpath;
1783
1784	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
1785
1786	if (val64 & VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN) {
1787
1788		val64 &= ~(VXGE_HW_RXMAC_VCFG0_UCAST_ALL_ADDR_EN |
1789			   VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN |
1790			   VXGE_HW_RXMAC_VCFG0_ALL_VID_EN);
1791
1792		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
1793	}
1794exit:
1795	return status;
1796}
1797
1798/*
1799 * vxge_hw_vpath_bcast_enable - Enable broadcast
1800 * @vp: Vpath handle.
1801 *
1802 * Enable receiving broadcasts.
1803 */
1804enum vxge_hw_status vxge_hw_vpath_bcast_enable(
1805			struct __vxge_hw_vpath_handle *vp)
1806{
1807	u64 val64;
1808	struct __vxge_hw_virtualpath *vpath;
1809	enum vxge_hw_status status = VXGE_HW_OK;
1810
1811	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
1812		status = VXGE_HW_ERR_INVALID_HANDLE;
1813		goto exit;
1814	}
1815
1816	vpath = vp->vpath;
1817
1818	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
1819
1820	if (!(val64 & VXGE_HW_RXMAC_VCFG0_BCAST_EN)) {
1821		val64 |= VXGE_HW_RXMAC_VCFG0_BCAST_EN;
1822		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
1823	}
1824exit:
1825	return status;
1826}
1827
1828/**
1829 * vxge_hw_vpath_mcast_enable - Enable multicast addresses.
1830 * @vp: Vpath handle.
1831 *
1832 * Enable Titan-e multicast addresses.
1833 * Returns: VXGE_HW_OK on success.
1834 *
1835 */
1836enum vxge_hw_status vxge_hw_vpath_mcast_enable(
1837			struct __vxge_hw_vpath_handle *vp)
1838{
1839	u64 val64;
1840	struct __vxge_hw_virtualpath *vpath;
1841	enum vxge_hw_status status = VXGE_HW_OK;
1842
1843	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
1844		status = VXGE_HW_ERR_INVALID_HANDLE;
1845		goto exit;
1846	}
1847
1848	vpath = vp->vpath;
1849
1850	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
1851
1852	if (!(val64 & VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN)) {
1853		val64 |= VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN;
1854		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
1855	}
1856exit:
1857	return status;
1858}
1859
1860/**
1861 * vxge_hw_vpath_mcast_disable - Disable  multicast addresses.
1862 * @vp: Vpath handle.
1863 *
1864 * Disable Titan-e multicast addresses.
1865 * Returns: VXGE_HW_OK - success.
1866 * VXGE_HW_ERR_INVALID_HANDLE - Invalid handle
1867 *
1868 */
1869enum vxge_hw_status
1870vxge_hw_vpath_mcast_disable(struct __vxge_hw_vpath_handle *vp)
1871{
1872	u64 val64;
1873	struct __vxge_hw_virtualpath *vpath;
1874	enum vxge_hw_status status = VXGE_HW_OK;
1875
1876	if ((vp == NULL) || (vp->vpath->ringh == NULL)) {
1877		status = VXGE_HW_ERR_INVALID_HANDLE;
1878		goto exit;
1879	}
1880
1881	vpath = vp->vpath;
1882
1883	val64 = readq(&vpath->vp_reg->rxmac_vcfg0);
1884
1885	if (val64 & VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN) {
1886		val64 &= ~VXGE_HW_RXMAC_VCFG0_MCAST_ALL_ADDR_EN;
1887		writeq(val64, &vpath->vp_reg->rxmac_vcfg0);
1888	}
1889exit:
1890	return status;
1891}
1892
1893/*
1894 * __vxge_hw_vpath_alarm_process - Process Alarms.
1895 * @vpath: Virtual Path.
1896 * @skip_alarms: Do not clear the alarms
1897 *
1898 * Process vpath alarms.
1899 *
1900 */
1901enum vxge_hw_status __vxge_hw_vpath_alarm_process(
1902			struct __vxge_hw_virtualpath *vpath,
1903			u32 skip_alarms)
1904{
1905	u64 val64;
1906	u64 alarm_status;
1907	u64 pic_status;
1908	struct __vxge_hw_device *hldev = NULL;
1909	enum vxge_hw_event alarm_event = VXGE_HW_EVENT_UNKNOWN;
1910	u64 mask64;
1911	struct vxge_hw_vpath_stats_sw_info *sw_stats;
1912	struct vxge_hw_vpath_reg __iomem *vp_reg;
1913
1914	if (vpath == NULL) {
1915		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
1916			alarm_event);
1917		goto out2;
1918	}
1919
1920	hldev = vpath->hldev;
1921	vp_reg = vpath->vp_reg;
1922	alarm_status = readq(&vp_reg->vpath_general_int_status);
1923
1924	if (alarm_status == VXGE_HW_ALL_FOXES) {
1925		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_SLOT_FREEZE,
1926			alarm_event);
1927		goto out;
1928	}
1929
1930	sw_stats = vpath->sw_stats;
1931
1932	if (alarm_status & ~(
1933		VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT |
1934		VXGE_HW_VPATH_GENERAL_INT_STATUS_PCI_INT |
1935		VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT |
1936		VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT)) {
1937		sw_stats->error_stats.unknown_alarms++;
1938
1939		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
1940			alarm_event);
1941		goto out;
1942	}
1943
1944	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_XMAC_INT) {
1945
1946		val64 = readq(&vp_reg->xgmac_vp_int_status);
1947
1948		if (val64 &
1949		VXGE_HW_XGMAC_VP_INT_STATUS_ASIC_NTWK_VP_ERR_ASIC_NTWK_VP_INT) {
1950
1951			val64 = readq(&vp_reg->asic_ntwk_vp_err_reg);
1952
1953			if (((val64 &
1954			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT) &&
1955			     (!(val64 &
1956				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK))) ||
1957			    ((val64 &
1958			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR) &&
1959			     (!(val64 &
1960				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR)
1961				     ))) {
1962				sw_stats->error_stats.network_sustained_fault++;
1963
1964				writeq(
1965				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT,
1966					&vp_reg->asic_ntwk_vp_err_mask);
1967
1968				__vxge_hw_device_handle_link_down_ind(hldev);
1969				alarm_event = VXGE_HW_SET_LEVEL(
1970					VXGE_HW_EVENT_LINK_DOWN, alarm_event);
1971			}
1972
1973			if (((val64 &
1974			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK) &&
1975			     (!(val64 &
1976				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT))) ||
1977			    ((val64 &
1978			      VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK_OCCURR) &&
1979			     (!(val64 &
1980				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_FLT_OCCURR)
1981				     ))) {
1982
1983				sw_stats->error_stats.network_sustained_ok++;
1984
1985				writeq(
1986				VXGE_HW_ASIC_NW_VP_ERR_REG_XMACJ_STN_OK,
1987					&vp_reg->asic_ntwk_vp_err_mask);
1988
1989				__vxge_hw_device_handle_link_up_ind(hldev);
1990				alarm_event = VXGE_HW_SET_LEVEL(
1991					VXGE_HW_EVENT_LINK_UP, alarm_event);
1992			}
1993
1994			writeq(VXGE_HW_INTR_MASK_ALL,
1995				&vp_reg->asic_ntwk_vp_err_reg);
1996
1997			alarm_event = VXGE_HW_SET_LEVEL(
1998				VXGE_HW_EVENT_ALARM_CLEARED, alarm_event);
1999
2000			if (skip_alarms)
2001				return VXGE_HW_OK;
2002		}
2003	}
2004
2005	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_PIC_INT) {
2006
2007		pic_status = readq(&vp_reg->vpath_ppif_int_status);
2008
2009		if (pic_status &
2010		    VXGE_HW_VPATH_PPIF_INT_STATUS_GENERAL_ERRORS_GENERAL_INT) {
2011
2012			val64 = readq(&vp_reg->general_errors_reg);
2013			mask64 = readq(&vp_reg->general_errors_mask);
2014
2015			if ((val64 &
2016				VXGE_HW_GENERAL_ERRORS_REG_INI_SERR_DET) &
2017				~mask64) {
2018				sw_stats->error_stats.ini_serr_det++;
2019
2020				alarm_event = VXGE_HW_SET_LEVEL(
2021					VXGE_HW_EVENT_SERR, alarm_event);
2022			}
2023
2024			if ((val64 &
2025			    VXGE_HW_GENERAL_ERRORS_REG_DBLGEN_FIFO0_OVRFLOW) &
2026				~mask64) {
2027				sw_stats->error_stats.dblgen_fifo0_overflow++;
2028
2029				alarm_event = VXGE_HW_SET_LEVEL(
2030					VXGE_HW_EVENT_FIFO_ERR, alarm_event);
2031			}
2032
2033			if ((val64 &
2034			    VXGE_HW_GENERAL_ERRORS_REG_STATSB_PIF_CHAIN_ERR) &
2035				~mask64)
2036				sw_stats->error_stats.statsb_pif_chain_error++;
2037
2038			if ((val64 &
2039			   VXGE_HW_GENERAL_ERRORS_REG_STATSB_DROP_TIMEOUT_REQ) &
2040				~mask64)
2041				sw_stats->error_stats.statsb_drop_timeout++;
2042
2043			if ((val64 &
2044				VXGE_HW_GENERAL_ERRORS_REG_TGT_ILLEGAL_ACCESS) &
2045				~mask64)
2046				sw_stats->error_stats.target_illegal_access++;
2047
2048			if (!skip_alarms) {
2049				writeq(VXGE_HW_INTR_MASK_ALL,
2050					&vp_reg->general_errors_reg);
2051				alarm_event = VXGE_HW_SET_LEVEL(
2052					VXGE_HW_EVENT_ALARM_CLEARED,
2053					alarm_event);
2054			}
2055		}
2056
2057		if (pic_status &
2058		    VXGE_HW_VPATH_PPIF_INT_STATUS_KDFCCTL_ERRORS_KDFCCTL_INT) {
2059
2060			val64 = readq(&vp_reg->kdfcctl_errors_reg);
2061			mask64 = readq(&vp_reg->kdfcctl_errors_mask);
2062
2063			if ((val64 &
2064			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_OVRWR) &
2065				~mask64) {
2066				sw_stats->error_stats.kdfcctl_fifo0_overwrite++;
2067
2068				alarm_event = VXGE_HW_SET_LEVEL(
2069					VXGE_HW_EVENT_FIFO_ERR,
2070					alarm_event);
2071			}
2072
2073			if ((val64 &
2074			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_POISON) &
2075				~mask64) {
2076				sw_stats->error_stats.kdfcctl_fifo0_poison++;
2077
2078				alarm_event = VXGE_HW_SET_LEVEL(
2079					VXGE_HW_EVENT_FIFO_ERR,
2080					alarm_event);
2081			}
2082
2083			if ((val64 &
2084			    VXGE_HW_KDFCCTL_ERRORS_REG_KDFCCTL_FIFO0_DMA_ERR) &
2085				~mask64) {
2086				sw_stats->error_stats.kdfcctl_fifo0_dma_error++;
2087
2088				alarm_event = VXGE_HW_SET_LEVEL(
2089					VXGE_HW_EVENT_FIFO_ERR,
2090					alarm_event);
2091			}
2092
2093			if (!skip_alarms) {
2094				writeq(VXGE_HW_INTR_MASK_ALL,
2095					&vp_reg->kdfcctl_errors_reg);
2096				alarm_event = VXGE_HW_SET_LEVEL(
2097					VXGE_HW_EVENT_ALARM_CLEARED,
2098					alarm_event);
2099			}
2100		}
2101
2102	}
2103
2104	if (alarm_status & VXGE_HW_VPATH_GENERAL_INT_STATUS_WRDMA_INT) {
2105
2106		val64 = readq(&vp_reg->wrdma_alarm_status);
2107
2108		if (val64 & VXGE_HW_WRDMA_ALARM_STATUS_PRC_ALARM_PRC_INT) {
2109
2110			val64 = readq(&vp_reg->prc_alarm_reg);
2111			mask64 = readq(&vp_reg->prc_alarm_mask);
2112
2113			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RING_BUMP)&
2114				~mask64)
2115				sw_stats->error_stats.prc_ring_bumps++;
2116
2117			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ERR) &
2118				~mask64) {
2119				sw_stats->error_stats.prc_rxdcm_sc_err++;
2120
2121				alarm_event = VXGE_HW_SET_LEVEL(
2122					VXGE_HW_EVENT_VPATH_ERR,
2123					alarm_event);
2124			}
2125
2126			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_RXDCM_SC_ABORT)
2127				& ~mask64) {
2128				sw_stats->error_stats.prc_rxdcm_sc_abort++;
2129
2130				alarm_event = VXGE_HW_SET_LEVEL(
2131						VXGE_HW_EVENT_VPATH_ERR,
2132						alarm_event);
2133			}
2134
2135			if ((val64 & VXGE_HW_PRC_ALARM_REG_PRC_QUANTA_SIZE_ERR)
2136				 & ~mask64) {
2137				sw_stats->error_stats.prc_quanta_size_err++;
2138
2139				alarm_event = VXGE_HW_SET_LEVEL(
2140					VXGE_HW_EVENT_VPATH_ERR,
2141					alarm_event);
2142			}
2143
2144			if (!skip_alarms) {
2145				writeq(VXGE_HW_INTR_MASK_ALL,
2146					&vp_reg->prc_alarm_reg);
2147				alarm_event = VXGE_HW_SET_LEVEL(
2148						VXGE_HW_EVENT_ALARM_CLEARED,
2149						alarm_event);
2150			}
2151		}
2152	}
2153out:
2154	hldev->stats.sw_dev_err_stats.vpath_alarms++;
2155out2:
2156	if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) ||
2157		(alarm_event == VXGE_HW_EVENT_UNKNOWN))
2158		return VXGE_HW_OK;
2159
2160	__vxge_hw_device_handle_error(hldev, vpath->vp_id, alarm_event);
2161
2162	if (alarm_event == VXGE_HW_EVENT_SERR)
2163		return VXGE_HW_ERR_CRITICAL;
2164
2165	return (alarm_event == VXGE_HW_EVENT_SLOT_FREEZE) ?
2166		VXGE_HW_ERR_SLOT_FREEZE :
2167		(alarm_event == VXGE_HW_EVENT_FIFO_ERR) ? VXGE_HW_ERR_FIFO :
2168		VXGE_HW_ERR_VPATH;
2169}
2170
2171/*
2172 * vxge_hw_vpath_alarm_process - Process Alarms.
2173 * @vpath: Virtual Path.
2174 * @skip_alarms: Do not clear the alarms
2175 *
2176 * Process vpath alarms.
2177 *
2178 */
2179enum vxge_hw_status vxge_hw_vpath_alarm_process(
2180			struct __vxge_hw_vpath_handle *vp,
2181			u32 skip_alarms)
2182{
2183	enum vxge_hw_status status = VXGE_HW_OK;
2184
2185	if (vp == NULL) {
2186		status = VXGE_HW_ERR_INVALID_HANDLE;
2187		goto exit;
2188	}
2189
2190	status = __vxge_hw_vpath_alarm_process(vp->vpath, skip_alarms);
2191exit:
2192	return status;
2193}
2194
2195/**
2196 * vxge_hw_vpath_msix_set - Associate MSIX vectors with TIM interrupts and
2197 *                            alrms
2198 * @vp: Virtual Path handle.
2199 * @tim_msix_id: MSIX vectors associated with VXGE_HW_MAX_INTR_PER_VP number of
2200 *             interrupts(Can be repeated). If fifo or ring are not enabled
2201 *             the MSIX vector for that should be set to 0
2202 * @alarm_msix_id: MSIX vector for alarm.
2203 *
2204 * This API will associate a given MSIX vector numbers with the four TIM
2205 * interrupts and alarm interrupt.
2206 */
2207void
2208vxge_hw_vpath_msix_set(struct __vxge_hw_vpath_handle *vp, int *tim_msix_id,
2209		       int alarm_msix_id)
2210{
2211	u64 val64;
2212	struct __vxge_hw_virtualpath *vpath = vp->vpath;
2213	struct vxge_hw_vpath_reg __iomem *vp_reg = vpath->vp_reg;
2214	u32 vp_id = vp->vpath->vp_id;
2215
2216	val64 =  VXGE_HW_INTERRUPT_CFG0_GROUP0_MSIX_FOR_TXTI(
2217		  (vp_id * 4) + tim_msix_id[0]) |
2218		 VXGE_HW_INTERRUPT_CFG0_GROUP1_MSIX_FOR_TXTI(
2219		  (vp_id * 4) + tim_msix_id[1]);
2220
2221	writeq(val64, &vp_reg->interrupt_cfg0);
2222
2223	writeq(VXGE_HW_INTERRUPT_CFG2_ALARM_MAP_TO_MSG(
2224			(vpath->hldev->first_vp_id * 4) + alarm_msix_id),
2225			&vp_reg->interrupt_cfg2);
2226
2227	if (vpath->hldev->config.intr_mode ==
2228					VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
2229		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
2230				VXGE_HW_ONE_SHOT_VECT1_EN_ONE_SHOT_VECT1_EN,
2231				0, 32), &vp_reg->one_shot_vect1_en);
2232	}
2233
2234	if (vpath->hldev->config.intr_mode ==
2235		VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
2236		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
2237				VXGE_HW_ONE_SHOT_VECT2_EN_ONE_SHOT_VECT2_EN,
2238				0, 32), &vp_reg->one_shot_vect2_en);
2239
2240		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
2241				VXGE_HW_ONE_SHOT_VECT3_EN_ONE_SHOT_VECT3_EN,
2242				0, 32), &vp_reg->one_shot_vect3_en);
2243	}
2244}
2245
2246/**
2247 * vxge_hw_vpath_msix_mask - Mask MSIX Vector.
2248 * @vp: Virtual Path handle.
2249 * @msix_id:  MSIX ID
2250 *
2251 * The function masks the msix interrupt for the given msix_id
2252 *
2253 * Returns: 0,
2254 * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
2255 * status.
2256 * See also:
2257 */
2258void
2259vxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vp, int msix_id)
2260{
2261	struct __vxge_hw_device *hldev = vp->vpath->hldev;
2262	__vxge_hw_pio_mem_write32_upper(
2263		(u32) vxge_bVALn(vxge_mBIT(msix_id  >> 2), 0, 32),
2264		&hldev->common_reg->set_msix_mask_vect[msix_id % 4]);
2265}
2266
2267/**
2268 * vxge_hw_vpath_msix_clear - Clear MSIX Vector.
2269 * @vp: Virtual Path handle.
2270 * @msix_id:  MSI ID
2271 *
2272 * The function clears the msix interrupt for the given msix_id
2273 *
2274 * Returns: 0,
2275 * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
2276 * status.
2277 * See also:
2278 */
2279void
2280vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id)
2281{
2282	struct __vxge_hw_device *hldev = vp->vpath->hldev;
2283	if (hldev->config.intr_mode ==
2284			VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
2285		__vxge_hw_pio_mem_write32_upper(
2286			(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
2287				&hldev->common_reg->
2288					clr_msix_one_shot_vec[msix_id%4]);
2289	} else {
2290		__vxge_hw_pio_mem_write32_upper(
2291			(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
2292				&hldev->common_reg->
2293					clear_msix_mask_vect[msix_id%4]);
2294	}
2295}
2296
2297/**
2298 * vxge_hw_vpath_msix_unmask - Unmask the MSIX Vector.
2299 * @vp: Virtual Path handle.
2300 * @msix_id:  MSI ID
2301 *
2302 * The function unmasks the msix interrupt for the given msix_id
2303 *
2304 * Returns: 0,
2305 * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
2306 * status.
2307 * See also:
2308 */
2309void
2310vxge_hw_vpath_msix_unmask(struct __vxge_hw_vpath_handle *vp, int msix_id)
2311{
2312	struct __vxge_hw_device *hldev = vp->vpath->hldev;
2313	__vxge_hw_pio_mem_write32_upper(
2314			(u32)vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
2315			&hldev->common_reg->clear_msix_mask_vect[msix_id%4]);
2316}
2317
2318/**
2319 * vxge_hw_vpath_msix_mask_all - Mask all MSIX vectors for the vpath.
2320 * @vp: Virtual Path handle.
2321 *
2322 * The function masks all msix interrupt for the given vpath
2323 *
2324 */
2325void
2326vxge_hw_vpath_msix_mask_all(struct __vxge_hw_vpath_handle *vp)
2327{
2328
2329	__vxge_hw_pio_mem_write32_upper(
2330		(u32)vxge_bVALn(vxge_mBIT(vp->vpath->vp_id), 0, 32),
2331		&vp->vpath->hldev->common_reg->set_msix_mask_all_vect);
2332}
2333
2334/**
2335 * vxge_hw_vpath_inta_mask_tx_rx - Mask Tx and Rx interrupts.
2336 * @vp: Virtual Path handle.
2337 *
2338 * Mask Tx and Rx vpath interrupts.
2339 *
2340 * See also: vxge_hw_vpath_inta_mask_tx_rx()
2341 */
2342void vxge_hw_vpath_inta_mask_tx_rx(struct __vxge_hw_vpath_handle *vp)
2343{
2344	u64	tim_int_mask0[4] = {[0 ...3] = 0};
2345	u32	tim_int_mask1[4] = {[0 ...3] = 0};
2346	u64	val64;
2347	struct __vxge_hw_device *hldev = vp->vpath->hldev;
2348
2349	VXGE_HW_DEVICE_TIM_INT_MASK_SET(tim_int_mask0,
2350		tim_int_mask1, vp->vpath->vp_id);
2351
2352	val64 = readq(&hldev->common_reg->tim_int_mask0);
2353
2354	if ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
2355		(tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
2356		writeq((tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
2357			tim_int_mask0[VXGE_HW_VPATH_INTR_RX] | val64),
2358			&hldev->common_reg->tim_int_mask0);
2359	}
2360
2361	val64 = readl(&hldev->common_reg->tim_int_mask1);
2362
2363	if ((tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
2364		(tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
2365		__vxge_hw_pio_mem_write32_upper(
2366			(tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
2367			tim_int_mask1[VXGE_HW_VPATH_INTR_RX] | val64),
2368			&hldev->common_reg->tim_int_mask1);
2369	}
2370}
2371
2372/**
2373 * vxge_hw_vpath_inta_unmask_tx_rx - Unmask Tx and Rx interrupts.
2374 * @vp: Virtual Path handle.
2375 *
2376 * Unmask Tx and Rx vpath interrupts.
2377 *
2378 * See also: vxge_hw_vpath_inta_mask_tx_rx()
2379 */
2380void vxge_hw_vpath_inta_unmask_tx_rx(struct __vxge_hw_vpath_handle *vp)
2381{
2382	u64	tim_int_mask0[4] = {[0 ...3] = 0};
2383	u32	tim_int_mask1[4] = {[0 ...3] = 0};
2384	u64	val64;
2385	struct __vxge_hw_device *hldev = vp->vpath->hldev;
2386
2387	VXGE_HW_DEVICE_TIM_INT_MASK_SET(tim_int_mask0,
2388		tim_int_mask1, vp->vpath->vp_id);
2389
2390	val64 = readq(&hldev->common_reg->tim_int_mask0);
2391
2392	if ((tim_int_mask0[VXGE_HW_VPATH_INTR_TX] != 0) ||
2393	   (tim_int_mask0[VXGE_HW_VPATH_INTR_RX] != 0)) {
2394		writeq((~(tim_int_mask0[VXGE_HW_VPATH_INTR_TX] |
2395			tim_int_mask0[VXGE_HW_VPATH_INTR_RX])) & val64,
2396			&hldev->common_reg->tim_int_mask0);
2397	}
2398
2399	if ((tim_int_mask1[VXGE_HW_VPATH_INTR_TX] != 0) ||
2400	   (tim_int_mask1[VXGE_HW_VPATH_INTR_RX] != 0)) {
2401		__vxge_hw_pio_mem_write32_upper(
2402			(~(tim_int_mask1[VXGE_HW_VPATH_INTR_TX] |
2403			  tim_int_mask1[VXGE_HW_VPATH_INTR_RX])) & val64,
2404			&hldev->common_reg->tim_int_mask1);
2405	}
2406}
2407
2408/**
2409 * vxge_hw_vpath_poll_rx - Poll Rx Virtual Path for completed
2410 * descriptors and process the same.
2411 * @ring: Handle to the ring object used for receive
2412 *
2413 * The function	polls the Rx for the completed	descriptors and	calls
2414 * the driver via supplied completion	callback.
2415 *
2416 * Returns: VXGE_HW_OK, if the polling is completed successful.
2417 * VXGE_HW_COMPLETIONS_REMAIN: There are still more completed
2418 * descriptors available which are yet to be processed.
2419 *
2420 * See also: vxge_hw_vpath_poll_rx()
2421 */
2422enum vxge_hw_status vxge_hw_vpath_poll_rx(struct __vxge_hw_ring *ring)
2423{
2424	u8 t_code;
2425	enum vxge_hw_status status = VXGE_HW_OK;
2426	void *first_rxdh;
2427	u64 val64 = 0;
2428	int new_count = 0;
2429
2430	ring->cmpl_cnt = 0;
2431
2432	status = vxge_hw_ring_rxd_next_completed(ring, &first_rxdh, &t_code);
2433	if (status == VXGE_HW_OK)
2434		ring->callback(ring, first_rxdh,
2435			t_code, ring->channel.userdata);
2436
2437	if (ring->cmpl_cnt != 0) {
2438		ring->doorbell_cnt += ring->cmpl_cnt;
2439		if (ring->doorbell_cnt >= ring->rxds_limit) {
2440			/*
2441			 * Each RxD is of 4 qwords, update the number of
2442			 * qwords replenished
2443			 */
2444			new_count = (ring->doorbell_cnt * 4);
2445
2446			/* For each block add 4 more qwords */
2447			ring->total_db_cnt += ring->doorbell_cnt;
2448			if (ring->total_db_cnt >= ring->rxds_per_block) {
2449				new_count += 4;
2450				/* Reset total count */
2451				ring->total_db_cnt %= ring->rxds_per_block;
2452			}
2453			writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(new_count),
2454				&ring->vp_reg->prc_rxd_doorbell);
2455			val64 =
2456			  readl(&ring->common_reg->titan_general_int_status);
2457			ring->doorbell_cnt = 0;
2458		}
2459	}
2460
2461	return status;
2462}
2463
2464/**
2465 * vxge_hw_vpath_poll_tx - Poll Tx for completed descriptors and process
2466 * the same.
2467 * @fifo: Handle to the fifo object used for non offload send
2468 *
2469 * The function polls the Tx for the completed descriptors and calls
2470 * the driver via supplied completion callback.
2471 *
2472 * Returns: VXGE_HW_OK, if the polling is completed successful.
2473 * VXGE_HW_COMPLETIONS_REMAIN: There are still more completed
2474 * descriptors available which are yet to be processed.
2475 */
2476enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo,
2477					struct sk_buff ***skb_ptr, int nr_skb,
2478					int *more)
2479{
2480	enum vxge_hw_fifo_tcode t_code;
2481	void *first_txdlh;
2482	enum vxge_hw_status status = VXGE_HW_OK;
2483	struct __vxge_hw_channel *channel;
2484
2485	channel = &fifo->channel;
2486
2487	status = vxge_hw_fifo_txdl_next_completed(fifo,
2488				&first_txdlh, &t_code);
2489	if (status == VXGE_HW_OK)
2490		if (fifo->callback(fifo, first_txdlh, t_code,
2491			channel->userdata, skb_ptr, nr_skb, more) != VXGE_HW_OK)
2492			status = VXGE_HW_COMPLETIONS_REMAIN;
2493
2494	return status;
2495}
2496