vxge.c revision 221167
1221167Sgnn/*-
2221167Sgnn * Copyright(c) 2002-2011 Exar Corp.
3221167Sgnn * All rights reserved.
4221167Sgnn *
5221167Sgnn * Redistribution and use in source and binary forms, with or without
6221167Sgnn * modification are permitted provided the following conditions are met:
7221167Sgnn *
8221167Sgnn *    1. Redistributions of source code must retain the above copyright notice,
9221167Sgnn *       this list of conditions and the following disclaimer.
10221167Sgnn *
11221167Sgnn *    2. Redistributions in binary form must reproduce the above copyright
12221167Sgnn *       notice, this list of conditions and the following disclaimer in the
13221167Sgnn *       documentation and/or other materials provided with the distribution.
14221167Sgnn *
15221167Sgnn *    3. Neither the name of the Exar Corporation nor the names of its
16221167Sgnn *       contributors may be used to endorse or promote products derived from
17221167Sgnn *       this software without specific prior written permission.
18221167Sgnn *
19221167Sgnn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20221167Sgnn * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21221167Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22221167Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23221167Sgnn * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24221167Sgnn * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25221167Sgnn * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26221167Sgnn * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27221167Sgnn * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28221167Sgnn * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29221167Sgnn * POSSIBILITY OF SUCH DAMAGE.
30221167Sgnn */
31221167Sgnn/*$FreeBSD: head/sys/dev/vxge/vxge.c 221167 2011-04-28 14:33:15Z gnn $*/
32221167Sgnn
33221167Sgnn#include <dev/vxge/vxge.h>
34221167Sgnn
35221167Sgnnstatic int vxge_pci_bd_no = -1;
36221167Sgnnstatic u32 vxge_drv_copyright = 0;
37221167Sgnnstatic u32 vxge_dev_ref_count = 0;
38221167Sgnnstatic u32 vxge_dev_req_reboot = 0;
39221167Sgnn
40221167Sgnnstatic int vpath_selector[VXGE_HAL_MAX_VIRTUAL_PATHS] = \
41221167Sgnn{0, 1, 3, 3, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, 31};
42221167Sgnn
43221167Sgnn/*
44221167Sgnn * vxge_probe
45221167Sgnn * Probes for x3100 devices
46221167Sgnn */
47221167Sgnnint
48221167Sgnnvxge_probe(device_t ndev)
49221167Sgnn{
50221167Sgnn	int err = ENXIO;
51221167Sgnn
52221167Sgnn	u16 pci_bd_no = 0;
53221167Sgnn	u16 pci_vendor_id = 0;
54221167Sgnn	u16 pci_device_id = 0;
55221167Sgnn
56221167Sgnn	char adapter_name[64];
57221167Sgnn
58221167Sgnn	pci_vendor_id = pci_get_vendor(ndev);
59221167Sgnn	if (pci_vendor_id != VXGE_PCI_VENDOR_ID)
60221167Sgnn		goto _exit0;
61221167Sgnn
62221167Sgnn	pci_device_id = pci_get_device(ndev);
63221167Sgnn
64221167Sgnn	if (pci_device_id == VXGE_PCI_DEVICE_ID_TITAN_1) {
65221167Sgnn
66221167Sgnn		pci_bd_no = (pci_get_bus(ndev) | pci_get_slot(ndev));
67221167Sgnn
68221167Sgnn		snprintf(adapter_name, sizeof(adapter_name),
69221167Sgnn		    VXGE_ADAPTER_NAME, pci_get_revid(ndev));
70221167Sgnn		device_set_desc_copy(ndev, adapter_name);
71221167Sgnn
72221167Sgnn		if (!vxge_drv_copyright) {
73221167Sgnn			device_printf(ndev, VXGE_COPYRIGHT);
74221167Sgnn			vxge_drv_copyright = 1;
75221167Sgnn		}
76221167Sgnn
77221167Sgnn		if (vxge_dev_req_reboot == 0) {
78221167Sgnn			vxge_pci_bd_no = pci_bd_no;
79221167Sgnn			err = BUS_PROBE_DEFAULT;
80221167Sgnn		} else {
81221167Sgnn			if (pci_bd_no != vxge_pci_bd_no) {
82221167Sgnn				vxge_pci_bd_no = pci_bd_no;
83221167Sgnn				err = BUS_PROBE_DEFAULT;
84221167Sgnn			}
85221167Sgnn		}
86221167Sgnn	}
87221167Sgnn
88221167Sgnn_exit0:
89221167Sgnn	return (err);
90221167Sgnn}
91221167Sgnn
92221167Sgnn/*
93221167Sgnn * vxge_attach
94221167Sgnn * Connects driver to the system if probe was success @ndev handle
95221167Sgnn */
96221167Sgnnint
97221167Sgnnvxge_attach(device_t ndev)
98221167Sgnn{
99221167Sgnn	int err = 0;
100221167Sgnn	vxge_dev_t *vdev;
101221167Sgnn	vxge_hal_device_t *hldev = NULL;
102221167Sgnn	vxge_hal_device_attr_t device_attr;
103221167Sgnn	vxge_free_resources_e error_level = VXGE_FREE_NONE;
104221167Sgnn
105221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
106221167Sgnn
107221167Sgnn	/* Get per-ndev buffer */
108221167Sgnn	vdev = (vxge_dev_t *) device_get_softc(ndev);
109221167Sgnn	if (!vdev)
110221167Sgnn		goto _exit0;
111221167Sgnn
112221167Sgnn	bzero(vdev, sizeof(vxge_dev_t));
113221167Sgnn
114221167Sgnn	vdev->ndev = ndev;
115221167Sgnn	strlcpy(vdev->ndev_name, "vxge", sizeof(vdev->ndev_name));
116221167Sgnn
117221167Sgnn	err = vxge_driver_config(vdev);
118221167Sgnn	if (err != 0)
119221167Sgnn		goto _exit0;
120221167Sgnn
121221167Sgnn	/* Initialize HAL driver */
122221167Sgnn	status = vxge_driver_init(vdev);
123221167Sgnn	if (status != VXGE_HAL_OK) {
124221167Sgnn		device_printf(vdev->ndev, "Failed to initialize driver\n");
125221167Sgnn		goto _exit0;
126221167Sgnn	}
127221167Sgnn	/* Enable PCI bus-master */
128221167Sgnn	pci_enable_busmaster(ndev);
129221167Sgnn
130221167Sgnn	/* Allocate resources */
131221167Sgnn	err = vxge_alloc_resources(vdev);
132221167Sgnn	if (err != 0) {
133221167Sgnn		device_printf(vdev->ndev, "resource allocation failed\n");
134221167Sgnn		goto _exit0;
135221167Sgnn	}
136221167Sgnn
137221167Sgnn	err = vxge_device_hw_info_get(vdev);
138221167Sgnn	if (err != 0) {
139221167Sgnn		error_level = VXGE_FREE_BAR2;
140221167Sgnn		goto _exit0;
141221167Sgnn	}
142221167Sgnn
143221167Sgnn	/* Get firmware default values for Device Configuration */
144221167Sgnn	vxge_hal_device_config_default_get(vdev->device_config);
145221167Sgnn
146221167Sgnn	/* Customize Device Configuration based on User request */
147221167Sgnn	vxge_vpath_config(vdev);
148221167Sgnn
149221167Sgnn	/* Allocate ISR resources */
150221167Sgnn	err = vxge_alloc_isr_resources(vdev);
151221167Sgnn	if (err != 0) {
152221167Sgnn		error_level = VXGE_FREE_ISR_RESOURCE;
153221167Sgnn		device_printf(vdev->ndev, "isr resource allocation failed\n");
154221167Sgnn		goto _exit0;
155221167Sgnn	}
156221167Sgnn
157221167Sgnn	/* HAL attributes */
158221167Sgnn	device_attr.bar0 = (u8 *) vdev->pdev->bar_info[0];
159221167Sgnn	device_attr.bar1 = (u8 *) vdev->pdev->bar_info[1];
160221167Sgnn	device_attr.bar2 = (u8 *) vdev->pdev->bar_info[2];
161221167Sgnn	device_attr.regh0 = (vxge_bus_res_t *) vdev->pdev->reg_map[0];
162221167Sgnn	device_attr.regh1 = (vxge_bus_res_t *) vdev->pdev->reg_map[1];
163221167Sgnn	device_attr.regh2 = (vxge_bus_res_t *) vdev->pdev->reg_map[2];
164221167Sgnn	device_attr.irqh = (pci_irq_h) vdev->config.isr_info[0].irq_handle;
165221167Sgnn	device_attr.cfgh = vdev->pdev;
166221167Sgnn	device_attr.pdev = vdev->pdev;
167221167Sgnn
168221167Sgnn	/* Initialize HAL Device */
169221167Sgnn	status = vxge_hal_device_initialize((vxge_hal_device_h *) &hldev,
170221167Sgnn	    &device_attr, vdev->device_config);
171221167Sgnn	if (status != VXGE_HAL_OK) {
172221167Sgnn		error_level = VXGE_FREE_ISR_RESOURCE;
173221167Sgnn		device_printf(vdev->ndev, "hal device initialization failed\n");
174221167Sgnn		goto _exit0;
175221167Sgnn	}
176221167Sgnn
177221167Sgnn	vdev->devh = hldev;
178221167Sgnn	vxge_hal_device_private_set(hldev, vdev);
179221167Sgnn
180221167Sgnn	if (vdev->is_privilaged) {
181221167Sgnn		err = vxge_firmware_verify(vdev);
182221167Sgnn		if (err != 0) {
183221167Sgnn			vxge_dev_req_reboot = 1;
184221167Sgnn			error_level = VXGE_FREE_TERMINATE_DEVICE;
185221167Sgnn			goto _exit0;
186221167Sgnn		}
187221167Sgnn	}
188221167Sgnn
189221167Sgnn	/* Allocate memory for vpath */
190221167Sgnn	vdev->vpaths = (vxge_vpath_t *)
191221167Sgnn	    vxge_mem_alloc(vdev->no_of_vpath * sizeof(vxge_vpath_t));
192221167Sgnn
193221167Sgnn	if (vdev->vpaths == NULL) {
194221167Sgnn		error_level = VXGE_FREE_TERMINATE_DEVICE;
195221167Sgnn		device_printf(vdev->ndev, "vpath memory allocation failed\n");
196221167Sgnn		goto _exit0;
197221167Sgnn	}
198221167Sgnn
199221167Sgnn	vdev->no_of_func = 1;
200221167Sgnn	if (vdev->is_privilaged) {
201221167Sgnn
202221167Sgnn		vxge_hal_func_mode_count(vdev->devh,
203221167Sgnn		    vdev->config.hw_info.function_mode, &vdev->no_of_func);
204221167Sgnn
205221167Sgnn		vxge_bw_priority_config(vdev);
206221167Sgnn	}
207221167Sgnn
208221167Sgnn	/* Initialize mutexes */
209221167Sgnn	vxge_mutex_init(vdev);
210221167Sgnn
211221167Sgnn	/* Initialize Media */
212221167Sgnn	vxge_media_init(vdev);
213221167Sgnn
214221167Sgnn	err = vxge_ifp_setup(ndev);
215221167Sgnn	if (err != 0) {
216221167Sgnn		error_level = VXGE_FREE_MEDIA;
217221167Sgnn		device_printf(vdev->ndev, "setting up interface failed\n");
218221167Sgnn		goto _exit0;
219221167Sgnn	}
220221167Sgnn
221221167Sgnn	err = vxge_isr_setup(vdev);
222221167Sgnn	if (err != 0) {
223221167Sgnn		error_level = VXGE_FREE_INTERFACE;
224221167Sgnn		device_printf(vdev->ndev,
225221167Sgnn		    "failed to associate interrupt handler with device\n");
226221167Sgnn		goto _exit0;
227221167Sgnn	}
228221167Sgnn	vxge_device_hw_info_print(vdev);
229221167Sgnn	vdev->is_active = TRUE;
230221167Sgnn
231221167Sgnn_exit0:
232221167Sgnn	if (error_level) {
233221167Sgnn		vxge_free_resources(ndev, error_level);
234221167Sgnn		err = ENXIO;
235221167Sgnn	}
236221167Sgnn
237221167Sgnn	return (err);
238221167Sgnn}
239221167Sgnn
240221167Sgnn/*
241221167Sgnn * vxge_detach
242221167Sgnn * Detaches driver from the Kernel subsystem
243221167Sgnn */
244221167Sgnnint
245221167Sgnnvxge_detach(device_t ndev)
246221167Sgnn{
247221167Sgnn	vxge_dev_t *vdev;
248221167Sgnn
249221167Sgnn	vdev = (vxge_dev_t *) device_get_softc(ndev);
250221167Sgnn	if (vdev->is_active) {
251221167Sgnn		vdev->is_active = FALSE;
252221167Sgnn		vxge_stop(vdev);
253221167Sgnn		vxge_free_resources(ndev, VXGE_FREE_ALL);
254221167Sgnn	}
255221167Sgnn
256221167Sgnn	return (0);
257221167Sgnn}
258221167Sgnn
259221167Sgnn/*
260221167Sgnn * vxge_shutdown
261221167Sgnn * To shutdown device before system shutdown
262221167Sgnn */
263221167Sgnnint
264221167Sgnnvxge_shutdown(device_t ndev)
265221167Sgnn{
266221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) device_get_softc(ndev);
267221167Sgnn	vxge_stop(vdev);
268221167Sgnn	return (0);
269221167Sgnn}
270221167Sgnn
271221167Sgnn/*
272221167Sgnn * vxge_init
273221167Sgnn * Initialize the interface
274221167Sgnn */
275221167Sgnnvoid
276221167Sgnnvxge_init(void *vdev_ptr)
277221167Sgnn{
278221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) vdev_ptr;
279221167Sgnn
280221167Sgnn	VXGE_DRV_LOCK(vdev);
281221167Sgnn	vxge_init_locked(vdev);
282221167Sgnn	VXGE_DRV_UNLOCK(vdev);
283221167Sgnn}
284221167Sgnn
285221167Sgnn/*
286221167Sgnn * vxge_init_locked
287221167Sgnn * Initialize the interface
288221167Sgnn */
289221167Sgnnvoid
290221167Sgnnvxge_init_locked(vxge_dev_t *vdev)
291221167Sgnn{
292221167Sgnn	int i, err = EINVAL;
293221167Sgnn	vxge_hal_device_t *hldev = vdev->devh;
294221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
295221167Sgnn	vxge_hal_vpath_h vpath_handle;
296221167Sgnn
297221167Sgnn	ifnet_t ifp = vdev->ifp;
298221167Sgnn
299221167Sgnn	/* If device is in running state, initializing is not required */
300221167Sgnn	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
301221167Sgnn		goto _exit0;
302221167Sgnn
303221167Sgnn	VXGE_DRV_LOCK_ASSERT(vdev);
304221167Sgnn
305221167Sgnn	/* Opening vpaths */
306221167Sgnn	err = vxge_vpath_open(vdev);
307221167Sgnn	if (err != 0)
308221167Sgnn		goto _exit1;
309221167Sgnn
310221167Sgnn	if (vdev->config.rth_enable) {
311221167Sgnn		status = vxge_rth_config(vdev);
312221167Sgnn		if (status != VXGE_HAL_OK)
313221167Sgnn			goto _exit1;
314221167Sgnn	}
315221167Sgnn
316221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
317221167Sgnn		vpath_handle = vxge_vpath_handle_get(vdev, i);
318221167Sgnn		if (!vpath_handle)
319221167Sgnn			continue;
320221167Sgnn
321221167Sgnn		/* check initial mtu before enabling the device */
322221167Sgnn		status = vxge_hal_device_mtu_check(vpath_handle, ifp->if_mtu);
323221167Sgnn		if (status != VXGE_HAL_OK) {
324221167Sgnn			device_printf(vdev->ndev,
325221167Sgnn			    "invalid mtu size %ld specified\n", ifp->if_mtu);
326221167Sgnn			goto _exit1;
327221167Sgnn		}
328221167Sgnn
329221167Sgnn		status = vxge_hal_vpath_mtu_set(vpath_handle, ifp->if_mtu);
330221167Sgnn		if (status != VXGE_HAL_OK) {
331221167Sgnn			device_printf(vdev->ndev,
332221167Sgnn			    "setting mtu in device failed\n");
333221167Sgnn			goto _exit1;
334221167Sgnn		}
335221167Sgnn	}
336221167Sgnn
337221167Sgnn	/* Enable HAL device */
338221167Sgnn	status = vxge_hal_device_enable(hldev);
339221167Sgnn	if (status != VXGE_HAL_OK) {
340221167Sgnn		device_printf(vdev->ndev, "failed to enable device\n");
341221167Sgnn		goto _exit1;
342221167Sgnn	}
343221167Sgnn
344221167Sgnn	if (vdev->config.intr_mode == VXGE_HAL_INTR_MODE_MSIX)
345221167Sgnn		vxge_msix_enable(vdev);
346221167Sgnn
347221167Sgnn	/* Checksum capability */
348221167Sgnn	ifp->if_hwassist = 0;
349221167Sgnn	if (ifp->if_capenable & IFCAP_TXCSUM)
350221167Sgnn		ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
351221167Sgnn
352221167Sgnn	if (ifp->if_capenable & IFCAP_TSO4)
353221167Sgnn		ifp->if_hwassist |= CSUM_TSO;
354221167Sgnn
355221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
356221167Sgnn		vpath_handle = vxge_vpath_handle_get(vdev, i);
357221167Sgnn		if (!vpath_handle)
358221167Sgnn			continue;
359221167Sgnn
360221167Sgnn		/* Enabling bcast for all vpath */
361221167Sgnn		status = vxge_hal_vpath_bcast_enable(vpath_handle);
362221167Sgnn		if (status != VXGE_HAL_OK)
363221167Sgnn			device_printf(vdev->ndev,
364221167Sgnn			    "can't enable bcast on vpath (%d)\n", i);
365221167Sgnn	}
366221167Sgnn
367221167Sgnn	/* Enable interrupts */
368221167Sgnn	vxge_hal_device_intr_enable(vdev->devh);
369221167Sgnn
370221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
371221167Sgnn		vpath_handle = vxge_vpath_handle_get(vdev, i);
372221167Sgnn		if (!vpath_handle)
373221167Sgnn			continue;
374221167Sgnn
375221167Sgnn		bzero(&(vdev->vpaths[i].driver_stats),
376221167Sgnn		    sizeof(vxge_drv_stats_t));
377221167Sgnn		status = vxge_hal_vpath_enable(vpath_handle);
378221167Sgnn		if (status != VXGE_HAL_OK)
379221167Sgnn			goto _exit2;
380221167Sgnn	}
381221167Sgnn
382221167Sgnn	vxge_os_mdelay(1000);
383221167Sgnn
384221167Sgnn	/* Device is initialized */
385221167Sgnn	vdev->is_initialized = TRUE;
386221167Sgnn
387221167Sgnn	/* Now inform the stack we're ready */
388221167Sgnn	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
389221167Sgnn	ifp->if_drv_flags |= IFF_DRV_RUNNING;
390221167Sgnn
391221167Sgnn	goto _exit0;
392221167Sgnn
393221167Sgnn_exit2:
394221167Sgnn	vxge_hal_device_intr_disable(vdev->devh);
395221167Sgnn	vxge_hal_device_disable(hldev);
396221167Sgnn
397221167Sgnn_exit1:
398221167Sgnn	vxge_vpath_close(vdev);
399221167Sgnn
400221167Sgnn_exit0:
401221167Sgnn	return;
402221167Sgnn}
403221167Sgnn
404221167Sgnn/*
405221167Sgnn * vxge_driver_init
406221167Sgnn * Initializes HAL driver
407221167Sgnn */
408221167Sgnnvxge_hal_status_e
409221167Sgnnvxge_driver_init(vxge_dev_t *vdev)
410221167Sgnn{
411221167Sgnn	vxge_hal_uld_cbs_t uld_callbacks;
412221167Sgnn	vxge_hal_driver_config_t driver_config;
413221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
414221167Sgnn
415221167Sgnn	/* Initialize HAL driver */
416221167Sgnn	if (!vxge_dev_ref_count) {
417221167Sgnn		bzero(&uld_callbacks, sizeof(vxge_hal_uld_cbs_t));
418221167Sgnn		bzero(&driver_config, sizeof(vxge_hal_driver_config_t));
419221167Sgnn
420221167Sgnn		uld_callbacks.link_up = vxge_link_up;
421221167Sgnn		uld_callbacks.link_down = vxge_link_down;
422221167Sgnn		uld_callbacks.crit_err = vxge_crit_error;
423221167Sgnn		uld_callbacks.sched_timer = NULL;
424221167Sgnn		uld_callbacks.xpak_alarm_log = NULL;
425221167Sgnn
426221167Sgnn		status = vxge_hal_driver_initialize(&driver_config,
427221167Sgnn		    &uld_callbacks);
428221167Sgnn		if (status != VXGE_HAL_OK) {
429221167Sgnn			device_printf(vdev->ndev,
430221167Sgnn			    "failed to initialize driver\n");
431221167Sgnn			goto _exit0;
432221167Sgnn		}
433221167Sgnn	}
434221167Sgnn	vxge_hal_driver_debug_set(VXGE_TRACE);
435221167Sgnn	vxge_dev_ref_count++;
436221167Sgnn
437221167Sgnn_exit0:
438221167Sgnn	return (status);
439221167Sgnn}
440221167Sgnn
441221167Sgnn/*
442221167Sgnn * vxge_driver_config
443221167Sgnn */
444221167Sgnnint
445221167Sgnnvxge_driver_config(vxge_dev_t *vdev)
446221167Sgnn{
447221167Sgnn	int i, err = 0;
448221167Sgnn	char temp_buffer[30];
449221167Sgnn
450221167Sgnn	vxge_bw_info_t bw_info;
451221167Sgnn
452221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.no_of_vpath", vdev->config,
453221167Sgnn	    no_of_vpath, VXGE_DEFAULT_USER_HARDCODED);
454221167Sgnn
455221167Sgnn	if (vdev->config.no_of_vpath == VXGE_DEFAULT_USER_HARDCODED)
456221167Sgnn		vdev->config.no_of_vpath = mp_ncpus;
457221167Sgnn
458221167Sgnn	if (vdev->config.no_of_vpath <= 0) {
459221167Sgnn		err = EINVAL;
460221167Sgnn		device_printf(vdev->ndev,
461221167Sgnn		    "Failed to load driver, \
462221167Sgnn		    invalid config : \'no_of_vpath\'\n");
463221167Sgnn		goto _exit0;
464221167Sgnn	}
465221167Sgnn
466221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.intr_coalesce", vdev->config,
467221167Sgnn	    intr_coalesce, VXGE_DEFAULT_CONFIG_DISABLE);
468221167Sgnn
469221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.rth_enable", vdev->config,
470221167Sgnn	    rth_enable, VXGE_DEFAULT_CONFIG_ENABLE);
471221167Sgnn
472221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.rth_bkt_sz", vdev->config,
473221167Sgnn	    rth_bkt_sz, VXGE_DEFAULT_RTH_BUCKET_SIZE);
474221167Sgnn
475221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.lro_enable", vdev->config,
476221167Sgnn	    lro_enable, VXGE_DEFAULT_CONFIG_ENABLE);
477221167Sgnn
478221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.tso_enable", vdev->config,
479221167Sgnn	    tso_enable, VXGE_DEFAULT_CONFIG_ENABLE);
480221167Sgnn
481221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.tx_steering", vdev->config,
482221167Sgnn	    tx_steering, VXGE_DEFAULT_CONFIG_DISABLE);
483221167Sgnn
484221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.msix_enable", vdev->config,
485221167Sgnn	    intr_mode, VXGE_HAL_INTR_MODE_MSIX);
486221167Sgnn
487221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.ifqmaxlen", vdev->config,
488221167Sgnn	    ifq_maxlen, VXGE_DEFAULT_CONFIG_IFQ_MAXLEN);
489221167Sgnn
490221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.port_mode", vdev->config,
491221167Sgnn	    port_mode, VXGE_DEFAULT_CONFIG_VALUE);
492221167Sgnn
493221167Sgnn	if (vdev->config.port_mode == VXGE_DEFAULT_USER_HARDCODED)
494221167Sgnn		vdev->config.port_mode = VXGE_DEFAULT_CONFIG_VALUE;
495221167Sgnn
496221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.l2_switch", vdev->config,
497221167Sgnn	    l2_switch, VXGE_DEFAULT_CONFIG_VALUE);
498221167Sgnn
499221167Sgnn	if (vdev->config.l2_switch == VXGE_DEFAULT_USER_HARDCODED)
500221167Sgnn		vdev->config.l2_switch = VXGE_DEFAULT_CONFIG_VALUE;
501221167Sgnn
502221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.fw_upgrade", vdev->config,
503221167Sgnn	    fw_option, VXGE_FW_UPGRADE_ALL);
504221167Sgnn
505221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.low_latency", vdev->config,
506221167Sgnn	    low_latency, VXGE_DEFAULT_CONFIG_DISABLE);
507221167Sgnn
508221167Sgnn	VXGE_GET_PARAM("hint.vxge.0.func_mode", vdev->config,
509221167Sgnn	    function_mode, VXGE_DEFAULT_CONFIG_VALUE);
510221167Sgnn
511221167Sgnn	if (vdev->config.function_mode == VXGE_DEFAULT_USER_HARDCODED)
512221167Sgnn		vdev->config.function_mode = VXGE_DEFAULT_CONFIG_VALUE;
513221167Sgnn
514221167Sgnn	if (!(is_multi_func(vdev->config.function_mode) ||
515221167Sgnn	    is_single_func(vdev->config.function_mode)))
516221167Sgnn		vdev->config.function_mode = VXGE_DEFAULT_CONFIG_VALUE;
517221167Sgnn
518221167Sgnn	for (i = 0; i < VXGE_HAL_MAX_FUNCTIONS; i++) {
519221167Sgnn
520221167Sgnn		bw_info.func_id = i;
521221167Sgnn
522221167Sgnn		sprintf(temp_buffer, "hint.vxge.0.bandwidth_%d", i);
523221167Sgnn		VXGE_GET_PARAM(temp_buffer, bw_info,
524221167Sgnn		    bandwidth, VXGE_DEFAULT_USER_HARDCODED);
525221167Sgnn
526221167Sgnn		if (bw_info.bandwidth == VXGE_DEFAULT_USER_HARDCODED)
527221167Sgnn			bw_info.bandwidth = VXGE_HAL_VPATH_BW_LIMIT_DEFAULT;
528221167Sgnn
529221167Sgnn		sprintf(temp_buffer, "hint.vxge.0.priority_%d", i);
530221167Sgnn		VXGE_GET_PARAM(temp_buffer, bw_info,
531221167Sgnn		    priority, VXGE_DEFAULT_USER_HARDCODED);
532221167Sgnn
533221167Sgnn		if (bw_info.priority == VXGE_DEFAULT_USER_HARDCODED)
534221167Sgnn			bw_info.priority = VXGE_HAL_VPATH_PRIORITY_DEFAULT;
535221167Sgnn
536221167Sgnn		vxge_os_memcpy(&vdev->config.bw_info[i], &bw_info,
537221167Sgnn		    sizeof(vxge_bw_info_t));
538221167Sgnn	}
539221167Sgnn
540221167Sgnn_exit0:
541221167Sgnn	return (err);
542221167Sgnn}
543221167Sgnn
544221167Sgnn/*
545221167Sgnn * vxge_stop
546221167Sgnn */
547221167Sgnnvoid
548221167Sgnnvxge_stop(vxge_dev_t *vdev)
549221167Sgnn{
550221167Sgnn	VXGE_DRV_LOCK(vdev);
551221167Sgnn	vxge_stop_locked(vdev);
552221167Sgnn	VXGE_DRV_UNLOCK(vdev);
553221167Sgnn}
554221167Sgnn
555221167Sgnn/*
556221167Sgnn * vxge_stop_locked
557221167Sgnn * Common code for both stop and part of reset.
558221167Sgnn * disables device, interrupts and closes vpaths handle
559221167Sgnn */
560221167Sgnnvoid
561221167Sgnnvxge_stop_locked(vxge_dev_t *vdev)
562221167Sgnn{
563221167Sgnn	u64 adapter_status = 0;
564221167Sgnn	vxge_hal_status_e status;
565221167Sgnn	vxge_hal_device_t *hldev = vdev->devh;
566221167Sgnn	ifnet_t ifp = vdev->ifp;
567221167Sgnn
568221167Sgnn	VXGE_DRV_LOCK_ASSERT(vdev);
569221167Sgnn
570221167Sgnn	/* If device is not in "Running" state, return */
571221167Sgnn	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
572221167Sgnn		return;
573221167Sgnn
574221167Sgnn	/* Set appropriate flags */
575221167Sgnn	vdev->is_initialized = FALSE;
576221167Sgnn	hldev->link_state = VXGE_HAL_LINK_NONE;
577221167Sgnn	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
578221167Sgnn	if_link_state_change(ifp, LINK_STATE_DOWN);
579221167Sgnn
580221167Sgnn	/* Disable interrupts */
581221167Sgnn	vxge_hal_device_intr_disable(hldev);
582221167Sgnn
583221167Sgnn	/* Disable HAL device */
584221167Sgnn	status = vxge_hal_device_disable(hldev);
585221167Sgnn	if (status != VXGE_HAL_OK) {
586221167Sgnn		vxge_hal_device_status(hldev, &adapter_status);
587221167Sgnn		device_printf(vdev->ndev,
588221167Sgnn		    "adapter status: 0x%llx\n", adapter_status);
589221167Sgnn	}
590221167Sgnn
591221167Sgnn	/* reset vpaths */
592221167Sgnn	vxge_vpath_reset(vdev);
593221167Sgnn
594221167Sgnn	vxge_os_mdelay(1000);
595221167Sgnn
596221167Sgnn	/* Close Vpaths */
597221167Sgnn	vxge_vpath_close(vdev);
598221167Sgnn}
599221167Sgnn
600221167Sgnnvoid
601221167Sgnnvxge_send(ifnet_t ifp)
602221167Sgnn{
603221167Sgnn	vxge_vpath_t *vpath;
604221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) ifp->if_softc;
605221167Sgnn
606221167Sgnn	vpath = &(vdev->vpaths[0]);
607221167Sgnn
608221167Sgnn	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
609221167Sgnn		if (VXGE_TX_TRYLOCK(vpath)) {
610221167Sgnn			vxge_send_locked(ifp, vpath);
611221167Sgnn			VXGE_TX_UNLOCK(vpath);
612221167Sgnn		}
613221167Sgnn	}
614221167Sgnn}
615221167Sgnn
616221167Sgnnstatic inline void
617221167Sgnnvxge_send_locked(ifnet_t ifp, vxge_vpath_t *vpath)
618221167Sgnn{
619221167Sgnn	mbuf_t m_head = NULL;
620221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
621221167Sgnn
622221167Sgnn	VXGE_TX_LOCK_ASSERT(vpath);
623221167Sgnn
624221167Sgnn	if ((!vdev->is_initialized) ||
625221167Sgnn	    ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
626221167Sgnn	    IFF_DRV_RUNNING))
627221167Sgnn		return;
628221167Sgnn
629221167Sgnn	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
630221167Sgnn		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
631221167Sgnn		if (m_head == NULL)
632221167Sgnn			break;
633221167Sgnn
634221167Sgnn		if (vxge_xmit(ifp, vpath, &m_head)) {
635221167Sgnn			if (m_head == NULL)
636221167Sgnn				break;
637221167Sgnn
638221167Sgnn			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
639221167Sgnn			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
640221167Sgnn			VXGE_DRV_STATS(vpath, tx_again);
641221167Sgnn			break;
642221167Sgnn		}
643221167Sgnn		/* Send a copy of the frame to the BPF listener */
644221167Sgnn		ETHER_BPF_MTAP(ifp, m_head);
645221167Sgnn	}
646221167Sgnn}
647221167Sgnn
648221167Sgnn#if __FreeBSD_version >= 800000
649221167Sgnn
650221167Sgnnint
651221167Sgnnvxge_mq_send(ifnet_t ifp, mbuf_t m_head)
652221167Sgnn{
653221167Sgnn	int i = 0, err = 0;
654221167Sgnn
655221167Sgnn	vxge_vpath_t *vpath;
656221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) ifp->if_softc;
657221167Sgnn
658221167Sgnn	if (vdev->config.tx_steering) {
659221167Sgnn		i = vxge_vpath_get(vdev, m_head);
660221167Sgnn	} else if ((m_head->m_flags & M_FLOWID) != 0) {
661221167Sgnn		i = m_head->m_pkthdr.flowid % vdev->no_of_vpath;
662221167Sgnn	}
663221167Sgnn
664221167Sgnn	vpath = &(vdev->vpaths[i]);
665221167Sgnn	if (VXGE_TX_TRYLOCK(vpath)) {
666221167Sgnn		err = vxge_mq_send_locked(ifp, vpath, m_head);
667221167Sgnn		VXGE_TX_UNLOCK(vpath);
668221167Sgnn	} else
669221167Sgnn		err = drbr_enqueue(ifp, vpath->br, m_head);
670221167Sgnn
671221167Sgnn	return (err);
672221167Sgnn}
673221167Sgnn
674221167Sgnnstatic inline int
675221167Sgnnvxge_mq_send_locked(ifnet_t ifp, vxge_vpath_t *vpath, mbuf_t m_head)
676221167Sgnn{
677221167Sgnn	int err = 0;
678221167Sgnn	mbuf_t next = NULL;
679221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
680221167Sgnn
681221167Sgnn	VXGE_TX_LOCK_ASSERT(vpath);
682221167Sgnn
683221167Sgnn	if ((!vdev->is_initialized) ||
684221167Sgnn	    ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
685221167Sgnn	    IFF_DRV_RUNNING)) {
686221167Sgnn		err = drbr_enqueue(ifp, vpath->br, m_head);
687221167Sgnn		goto _exit0;
688221167Sgnn	}
689221167Sgnn	if (m_head == NULL) {
690221167Sgnn		next = drbr_dequeue(ifp, vpath->br);
691221167Sgnn	} else if (drbr_needs_enqueue(ifp, vpath->br)) {
692221167Sgnn		if ((err = drbr_enqueue(ifp, vpath->br, m_head)) != 0)
693221167Sgnn			goto _exit0;
694221167Sgnn		next = drbr_dequeue(ifp, vpath->br);
695221167Sgnn	} else
696221167Sgnn		next = m_head;
697221167Sgnn
698221167Sgnn	/* Process the queue */
699221167Sgnn	while (next != NULL) {
700221167Sgnn		if ((err = vxge_xmit(ifp, vpath, &next)) != 0) {
701221167Sgnn			if (next == NULL)
702221167Sgnn				break;
703221167Sgnn
704221167Sgnn			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
705221167Sgnn			err = drbr_enqueue(ifp, vpath->br, next);
706221167Sgnn			VXGE_DRV_STATS(vpath, tx_again);
707221167Sgnn			break;
708221167Sgnn		}
709221167Sgnn		drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
710221167Sgnn
711221167Sgnn		/* Send a copy of the frame to the BPF listener */
712221167Sgnn		ETHER_BPF_MTAP(ifp, next);
713221167Sgnn		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
714221167Sgnn			break;
715221167Sgnn
716221167Sgnn		next = drbr_dequeue(ifp, vpath->br);
717221167Sgnn	}
718221167Sgnn
719221167Sgnn_exit0:
720221167Sgnn	return (err);
721221167Sgnn}
722221167Sgnn
723221167Sgnnvoid
724221167Sgnnvxge_mq_qflush(ifnet_t ifp)
725221167Sgnn{
726221167Sgnn	int i;
727221167Sgnn	mbuf_t m_head;
728221167Sgnn	vxge_vpath_t *vpath;
729221167Sgnn
730221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) ifp->if_softc;
731221167Sgnn
732221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
733221167Sgnn		vpath = &(vdev->vpaths[i]);
734221167Sgnn		if (!vpath->handle)
735221167Sgnn			continue;
736221167Sgnn
737221167Sgnn		VXGE_TX_LOCK(vpath);
738221167Sgnn		while ((m_head = buf_ring_dequeue_sc(vpath->br)) != NULL)
739221167Sgnn			vxge_free_packet(m_head);
740221167Sgnn
741221167Sgnn		VXGE_TX_UNLOCK(vpath);
742221167Sgnn	}
743221167Sgnn	if_qflush(ifp);
744221167Sgnn}
745221167Sgnn#endif
746221167Sgnn
747221167Sgnnstatic inline int
748221167Sgnnvxge_xmit(ifnet_t ifp, vxge_vpath_t *vpath, mbuf_t *m_headp)
749221167Sgnn{
750221167Sgnn	int err, num_segs = 0;
751221167Sgnn	u32 txdl_avail, dma_index, tagged = 0;
752221167Sgnn
753221167Sgnn	dma_addr_t dma_addr;
754221167Sgnn	bus_size_t dma_sizes;
755221167Sgnn
756221167Sgnn	void *dtr_priv;
757221167Sgnn	vxge_txdl_priv_t *txdl_priv;
758221167Sgnn	vxge_hal_txdl_h txdlh;
759221167Sgnn	vxge_hal_status_e status;
760221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
761221167Sgnn
762221167Sgnn	VXGE_DRV_STATS(vpath, tx_xmit);
763221167Sgnn
764221167Sgnn	txdl_avail = vxge_hal_fifo_free_txdl_count_get(vpath->handle);
765221167Sgnn	if (txdl_avail < VXGE_TX_LOW_THRESHOLD) {
766221167Sgnn
767221167Sgnn		VXGE_DRV_STATS(vpath, tx_low_dtr_cnt);
768221167Sgnn		err = ENOBUFS;
769221167Sgnn		goto _exit0;
770221167Sgnn	}
771221167Sgnn
772221167Sgnn	/* Reserve descriptors */
773221167Sgnn	status = vxge_hal_fifo_txdl_reserve(vpath->handle, &txdlh, &dtr_priv);
774221167Sgnn	if (status != VXGE_HAL_OK) {
775221167Sgnn		VXGE_DRV_STATS(vpath, tx_reserve_failed);
776221167Sgnn		err = ENOBUFS;
777221167Sgnn		goto _exit0;
778221167Sgnn	}
779221167Sgnn
780221167Sgnn	/* Update Tx private structure for this descriptor */
781221167Sgnn	txdl_priv = (vxge_txdl_priv_t *) dtr_priv;
782221167Sgnn
783221167Sgnn	/*
784221167Sgnn	 * Map the packet for DMA.
785221167Sgnn	 * Returns number of segments through num_segs.
786221167Sgnn	 */
787221167Sgnn	err = vxge_dma_mbuf_coalesce(vpath->dma_tag_tx, txdl_priv->dma_map,
788221167Sgnn	    m_headp, txdl_priv->dma_buffers, &num_segs);
789221167Sgnn
790221167Sgnn	if (vpath->driver_stats.tx_max_frags < num_segs)
791221167Sgnn		vpath->driver_stats.tx_max_frags = num_segs;
792221167Sgnn
793221167Sgnn	if (err == ENOMEM) {
794221167Sgnn		VXGE_DRV_STATS(vpath, tx_no_dma_setup);
795221167Sgnn		vxge_hal_fifo_txdl_free(vpath->handle, txdlh);
796221167Sgnn		goto _exit0;
797221167Sgnn	} else if (err != 0) {
798221167Sgnn		vxge_free_packet(*m_headp);
799221167Sgnn		VXGE_DRV_STATS(vpath, tx_no_dma_setup);
800221167Sgnn		vxge_hal_fifo_txdl_free(vpath->handle, txdlh);
801221167Sgnn		goto _exit0;
802221167Sgnn	}
803221167Sgnn
804221167Sgnn	txdl_priv->mbuf_pkt = *m_headp;
805221167Sgnn
806221167Sgnn	/* Set VLAN tag in descriptor only if this packet has it */
807221167Sgnn	if ((*m_headp)->m_flags & M_VLANTAG)
808221167Sgnn		vxge_hal_fifo_txdl_vlan_set(txdlh,
809221167Sgnn		    (*m_headp)->m_pkthdr.ether_vtag);
810221167Sgnn
811221167Sgnn	/* Set descriptor buffer for header and each fragment/segment */
812221167Sgnn	for (dma_index = 0; dma_index < num_segs; dma_index++) {
813221167Sgnn
814221167Sgnn		dma_sizes = txdl_priv->dma_buffers[dma_index].ds_len;
815221167Sgnn		dma_addr = htole64(txdl_priv->dma_buffers[dma_index].ds_addr);
816221167Sgnn
817221167Sgnn		vxge_hal_fifo_txdl_buffer_set(vpath->handle, txdlh, dma_index,
818221167Sgnn		    dma_addr, dma_sizes);
819221167Sgnn	}
820221167Sgnn
821221167Sgnn	/* Pre-write Sync of mapping */
822221167Sgnn	bus_dmamap_sync(vpath->dma_tag_tx, txdl_priv->dma_map,
823221167Sgnn	    BUS_DMASYNC_PREWRITE);
824221167Sgnn
825221167Sgnn	if ((*m_headp)->m_pkthdr.csum_flags & CSUM_TSO) {
826221167Sgnn		if ((*m_headp)->m_pkthdr.tso_segsz) {
827221167Sgnn			VXGE_DRV_STATS(vpath, tx_tso);
828221167Sgnn			vxge_hal_fifo_txdl_lso_set(txdlh,
829221167Sgnn			    VXGE_HAL_FIFO_LSO_FRM_ENCAP_AUTO,
830221167Sgnn			    (*m_headp)->m_pkthdr.tso_segsz);
831221167Sgnn		}
832221167Sgnn	}
833221167Sgnn
834221167Sgnn	/* Checksum */
835221167Sgnn	if (ifp->if_hwassist > 0) {
836221167Sgnn		vxge_hal_fifo_txdl_cksum_set_bits(txdlh,
837221167Sgnn		    VXGE_HAL_FIFO_TXD_TX_CKO_IPV4_EN |
838221167Sgnn		    VXGE_HAL_FIFO_TXD_TX_CKO_TCP_EN |
839221167Sgnn		    VXGE_HAL_FIFO_TXD_TX_CKO_UDP_EN);
840221167Sgnn	}
841221167Sgnn
842221167Sgnn	if ((vxge_hal_device_check_id(vdev->devh) == VXGE_HAL_CARD_TITAN_1A) &&
843221167Sgnn	    (vdev->hw_fw_version >= VXGE_FW_VERSION(1, 8, 0)))
844221167Sgnn		tagged = 1;
845221167Sgnn
846221167Sgnn	vxge_hal_fifo_txdl_post(vpath->handle, txdlh, tagged);
847221167Sgnn	VXGE_DRV_STATS(vpath, tx_posted);
848221167Sgnn
849221167Sgnn_exit0:
850221167Sgnn	return (err);
851221167Sgnn}
852221167Sgnn
853221167Sgnn/*
854221167Sgnn * vxge_tx_replenish
855221167Sgnn * Allocate buffers and set them into descriptors for later use
856221167Sgnn */
857221167Sgnn/* ARGSUSED */
858221167Sgnnvxge_hal_status_e
859221167Sgnnvxge_tx_replenish(vxge_hal_vpath_h vpath_handle, vxge_hal_txdl_h txdlh,
860221167Sgnn    void *dtr_priv, u32 dtr_index, void *userdata, vxge_hal_reopen_e reopen)
861221167Sgnn{
862221167Sgnn	int err = 0;
863221167Sgnn
864221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
865221167Sgnn	vxge_txdl_priv_t *txdl_priv = (vxge_txdl_priv_t *) dtr_priv;
866221167Sgnn
867221167Sgnn	err = bus_dmamap_create(vpath->dma_tag_tx, BUS_DMA_NOWAIT,
868221167Sgnn	    &txdl_priv->dma_map);
869221167Sgnn
870221167Sgnn	return ((err == 0) ? VXGE_HAL_OK : VXGE_HAL_FAIL);
871221167Sgnn}
872221167Sgnn
873221167Sgnn/*
874221167Sgnn * vxge_tx_compl
875221167Sgnn * If the interrupt is due to Tx completion, free the sent buffer
876221167Sgnn */
877221167Sgnnvxge_hal_status_e
878221167Sgnnvxge_tx_compl(vxge_hal_vpath_h vpath_handle, vxge_hal_txdl_h txdlh,
879221167Sgnn    void *dtr_priv, vxge_hal_fifo_tcode_e t_code, void *userdata)
880221167Sgnn{
881221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
882221167Sgnn
883221167Sgnn	vxge_txdl_priv_t *txdl_priv;
884221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
885221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
886221167Sgnn
887221167Sgnn	ifnet_t ifp = vdev->ifp;
888221167Sgnn
889221167Sgnn	VXGE_TX_LOCK(vpath);
890221167Sgnn
891221167Sgnn	/*
892221167Sgnn	 * For each completed descriptor
893221167Sgnn	 * Get private structure, free buffer, do unmapping, and free descriptor
894221167Sgnn	 */
895221167Sgnn
896221167Sgnn	do {
897221167Sgnn		VXGE_DRV_STATS(vpath, tx_compl);
898221167Sgnn		if (t_code != VXGE_HAL_FIFO_T_CODE_OK) {
899221167Sgnn			device_printf(vdev->ndev, "tx transfer code %d\n",
900221167Sgnn			    t_code);
901221167Sgnn
902221167Sgnn			ifp->if_oerrors++;
903221167Sgnn			VXGE_DRV_STATS(vpath, tx_tcode);
904221167Sgnn			vxge_hal_fifo_handle_tcode(vpath_handle, txdlh, t_code);
905221167Sgnn		}
906221167Sgnn		ifp->if_opackets++;
907221167Sgnn		txdl_priv = (vxge_txdl_priv_t *) dtr_priv;
908221167Sgnn
909221167Sgnn		bus_dmamap_unload(vpath->dma_tag_tx, txdl_priv->dma_map);
910221167Sgnn
911221167Sgnn		vxge_free_packet(txdl_priv->mbuf_pkt);
912221167Sgnn		vxge_hal_fifo_txdl_free(vpath->handle, txdlh);
913221167Sgnn
914221167Sgnn	} while (vxge_hal_fifo_txdl_next_completed(vpath_handle, &txdlh,
915221167Sgnn	    &dtr_priv, &t_code) == VXGE_HAL_OK);
916221167Sgnn
917221167Sgnn
918221167Sgnn	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
919221167Sgnn	VXGE_TX_UNLOCK(vpath);
920221167Sgnn
921221167Sgnn	return (status);
922221167Sgnn}
923221167Sgnn
924221167Sgnn/* ARGSUSED */
925221167Sgnnvoid
926221167Sgnnvxge_tx_term(vxge_hal_vpath_h vpath_handle, vxge_hal_txdl_h txdlh,
927221167Sgnn    void *dtr_priv, vxge_hal_txdl_state_e state,
928221167Sgnn    void *userdata, vxge_hal_reopen_e reopen)
929221167Sgnn{
930221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
931221167Sgnn	vxge_txdl_priv_t *txdl_priv = (vxge_txdl_priv_t *) dtr_priv;
932221167Sgnn
933221167Sgnn	if (state != VXGE_HAL_TXDL_STATE_POSTED)
934221167Sgnn		return;
935221167Sgnn
936221167Sgnn	if (txdl_priv != NULL) {
937221167Sgnn		bus_dmamap_sync(vpath->dma_tag_tx, txdl_priv->dma_map,
938221167Sgnn		    BUS_DMASYNC_POSTWRITE);
939221167Sgnn
940221167Sgnn		bus_dmamap_unload(vpath->dma_tag_tx, txdl_priv->dma_map);
941221167Sgnn		bus_dmamap_destroy(vpath->dma_tag_tx, txdl_priv->dma_map);
942221167Sgnn		vxge_free_packet(txdl_priv->mbuf_pkt);
943221167Sgnn	}
944221167Sgnn
945221167Sgnn	/* Free the descriptor */
946221167Sgnn	vxge_hal_fifo_txdl_free(vpath->handle, txdlh);
947221167Sgnn}
948221167Sgnn
949221167Sgnn/*
950221167Sgnn * vxge_rx_replenish
951221167Sgnn * Allocate buffers and set them into descriptors for later use
952221167Sgnn */
953221167Sgnn/* ARGSUSED */
954221167Sgnnvxge_hal_status_e
955221167Sgnnvxge_rx_replenish(vxge_hal_vpath_h vpath_handle, vxge_hal_rxd_h rxdh,
956221167Sgnn    void *dtr_priv, u32 dtr_index, void *userdata, vxge_hal_reopen_e reopen)
957221167Sgnn{
958221167Sgnn	int err = 0;
959221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
960221167Sgnn
961221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
962221167Sgnn	vxge_rxd_priv_t *rxd_priv = (vxge_rxd_priv_t *) dtr_priv;
963221167Sgnn
964221167Sgnn	/* Create DMA map for these descriptors */
965221167Sgnn	err = bus_dmamap_create(vpath->dma_tag_rx, BUS_DMA_NOWAIT,
966221167Sgnn	    &rxd_priv->dma_map);
967221167Sgnn	if (err == 0) {
968221167Sgnn		if (vxge_rx_rxd_1b_set(vpath, rxdh, dtr_priv)) {
969221167Sgnn			bus_dmamap_destroy(vpath->dma_tag_rx,
970221167Sgnn			    rxd_priv->dma_map);
971221167Sgnn			status = VXGE_HAL_FAIL;
972221167Sgnn		}
973221167Sgnn	}
974221167Sgnn
975221167Sgnn	return (status);
976221167Sgnn}
977221167Sgnn
978221167Sgnn/*
979221167Sgnn * vxge_rx_compl
980221167Sgnn */
981221167Sgnnvxge_hal_status_e
982221167Sgnnvxge_rx_compl(vxge_hal_vpath_h vpath_handle, vxge_hal_rxd_h rxdh,
983221167Sgnn    void *dtr_priv, u8 t_code, void *userdata)
984221167Sgnn{
985221167Sgnn	mbuf_t mbuf_up;
986221167Sgnn
987221167Sgnn	vxge_rxd_priv_t *rxd_priv;
988221167Sgnn	vxge_hal_ring_rxd_info_t ext_info;
989221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
990221167Sgnn
991221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
992221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
993221167Sgnn
994221167Sgnn	struct lro_entry *queued = NULL;
995221167Sgnn	struct lro_ctrl *lro = &vpath->lro;
996221167Sgnn
997221167Sgnn	/* get the interface pointer */
998221167Sgnn	ifnet_t ifp = vdev->ifp;
999221167Sgnn
1000221167Sgnn	do {
1001221167Sgnn		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1002221167Sgnn			vxge_hal_ring_rxd_post(vpath_handle, rxdh);
1003221167Sgnn			status = VXGE_HAL_FAIL;
1004221167Sgnn			break;
1005221167Sgnn		}
1006221167Sgnn
1007221167Sgnn		VXGE_DRV_STATS(vpath, rx_compl);
1008221167Sgnn		rxd_priv = (vxge_rxd_priv_t *) dtr_priv;
1009221167Sgnn
1010221167Sgnn		/* Gets details of mbuf i.e., packet length */
1011221167Sgnn		vxge_rx_rxd_1b_get(vpath, rxdh, dtr_priv);
1012221167Sgnn
1013221167Sgnn		/*
1014221167Sgnn		 * Prepare one buffer to send it to upper layer Since upper
1015221167Sgnn		 * layer frees the buffer do not use rxd_priv->mbuf_pkt.
1016221167Sgnn		 * Meanwhile prepare a new buffer, do mapping, use with the
1017221167Sgnn		 * current descriptor and post descriptor back to ring vpath
1018221167Sgnn		 */
1019221167Sgnn		mbuf_up = rxd_priv->mbuf_pkt;
1020221167Sgnn		if (t_code != VXGE_HAL_RING_RXD_T_CODE_OK) {
1021221167Sgnn
1022221167Sgnn			ifp->if_ierrors++;
1023221167Sgnn			VXGE_DRV_STATS(vpath, rx_tcode);
1024221167Sgnn			status = vxge_hal_ring_handle_tcode(vpath_handle,
1025221167Sgnn			    rxdh, t_code);
1026221167Sgnn
1027221167Sgnn			/*
1028221167Sgnn			 * If transfer code is not for unknown protocols and
1029221167Sgnn			 * vxge_hal_device_handle_tcode is NOT returned
1030221167Sgnn			 * VXGE_HAL_OK
1031221167Sgnn			 * drop this packet and increment rx_tcode stats
1032221167Sgnn			 */
1033221167Sgnn			if ((status != VXGE_HAL_OK) &&
1034221167Sgnn			    (t_code != VXGE_HAL_RING_T_CODE_L3_PKT_ERR)) {
1035221167Sgnn
1036221167Sgnn				vxge_free_packet(mbuf_up);
1037221167Sgnn				vxge_hal_ring_rxd_post(vpath_handle, rxdh);
1038221167Sgnn				continue;
1039221167Sgnn			}
1040221167Sgnn		}
1041221167Sgnn
1042221167Sgnn		if (vxge_rx_rxd_1b_set(vpath, rxdh, dtr_priv)) {
1043221167Sgnn			/*
1044221167Sgnn			 * If unable to allocate buffer, post descriptor back
1045221167Sgnn			 * to vpath for future processing of same packet.
1046221167Sgnn			 */
1047221167Sgnn			vxge_hal_ring_rxd_post(vpath_handle, rxdh);
1048221167Sgnn			continue;
1049221167Sgnn		}
1050221167Sgnn
1051221167Sgnn		/* Get the extended information */
1052221167Sgnn		vxge_hal_ring_rxd_1b_info_get(vpath_handle, rxdh, &ext_info);
1053221167Sgnn
1054221167Sgnn		/* post descriptor with newly allocated mbuf back to vpath */
1055221167Sgnn		vxge_hal_ring_rxd_post(vpath_handle, rxdh);
1056221167Sgnn		vpath->rxd_posted++;
1057221167Sgnn
1058221167Sgnn		if (vpath->rxd_posted % VXGE_RXD_REPLENISH_COUNT == 0)
1059221167Sgnn			vxge_hal_ring_rxd_post_post_db(vpath_handle);
1060221167Sgnn
1061221167Sgnn		/*
1062221167Sgnn		 * Set successfully computed checksums in the mbuf.
1063221167Sgnn		 * Leave the rest to the stack to be reverified.
1064221167Sgnn		 */
1065221167Sgnn		vxge_rx_checksum(ext_info, mbuf_up);
1066221167Sgnn
1067221167Sgnn#if __FreeBSD_version >= 800000
1068221167Sgnn		mbuf_up->m_flags |= M_FLOWID;
1069221167Sgnn		mbuf_up->m_pkthdr.flowid = vpath->vp_index;
1070221167Sgnn#endif
1071221167Sgnn		/* Post-Read sync for buffers */
1072221167Sgnn		bus_dmamap_sync(vpath->dma_tag_rx, rxd_priv->dma_map,
1073221167Sgnn		    BUS_DMASYNC_POSTREAD);
1074221167Sgnn
1075221167Sgnn		vxge_rx_input(ifp, mbuf_up, vpath);
1076221167Sgnn
1077221167Sgnn	} while (vxge_hal_ring_rxd_next_completed(vpath_handle, &rxdh,
1078221167Sgnn	    &dtr_priv, &t_code) == VXGE_HAL_OK);
1079221167Sgnn
1080221167Sgnn	/* Flush any outstanding LRO work */
1081221167Sgnn	if (vpath->lro_enable && vpath->lro.lro_cnt) {
1082221167Sgnn		while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
1083221167Sgnn			SLIST_REMOVE_HEAD(&lro->lro_active, next);
1084221167Sgnn			tcp_lro_flush(lro, queued);
1085221167Sgnn		}
1086221167Sgnn	}
1087221167Sgnn
1088221167Sgnn	return (status);
1089221167Sgnn}
1090221167Sgnn
1091221167Sgnnstatic inline void
1092221167Sgnnvxge_rx_input(ifnet_t ifp, mbuf_t mbuf_up, vxge_vpath_t *vpath)
1093221167Sgnn{
1094221167Sgnn	if (vpath->lro_enable && vpath->lro.lro_cnt) {
1095221167Sgnn		if (tcp_lro_rx(&vpath->lro, mbuf_up, 0) == 0)
1096221167Sgnn			return;
1097221167Sgnn	}
1098221167Sgnn	(*ifp->if_input) (ifp, mbuf_up);
1099221167Sgnn}
1100221167Sgnn
1101221167Sgnnstatic inline void
1102221167Sgnnvxge_rx_checksum(vxge_hal_ring_rxd_info_t ext_info, mbuf_t mbuf_up)
1103221167Sgnn{
1104221167Sgnn
1105221167Sgnn	if (!(ext_info.proto & VXGE_HAL_FRAME_PROTO_IP_FRAG) &&
1106221167Sgnn	    (ext_info.proto & VXGE_HAL_FRAME_PROTO_TCP_OR_UDP) &&
1107221167Sgnn	    ext_info.l3_cksum_valid && ext_info.l4_cksum_valid) {
1108221167Sgnn
1109221167Sgnn		mbuf_up->m_pkthdr.csum_data = htons(0xffff);
1110221167Sgnn
1111221167Sgnn		mbuf_up->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
1112221167Sgnn		mbuf_up->m_pkthdr.csum_flags |= CSUM_IP_VALID;
1113221167Sgnn		mbuf_up->m_pkthdr.csum_flags |=
1114221167Sgnn		    (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
1115221167Sgnn
1116221167Sgnn	} else {
1117221167Sgnn
1118221167Sgnn		if (ext_info.vlan) {
1119221167Sgnn			mbuf_up->m_pkthdr.ether_vtag = ext_info.vlan;
1120221167Sgnn			mbuf_up->m_flags |= M_VLANTAG;
1121221167Sgnn		}
1122221167Sgnn	}
1123221167Sgnn}
1124221167Sgnn
1125221167Sgnn/*
1126221167Sgnn * vxge_rx_term During unload terminate and free all descriptors
1127221167Sgnn * @vpath_handle Rx vpath Handle @rxdh Rx Descriptor Handle @state Descriptor
1128221167Sgnn * State @userdata Per-adapter Data @reopen vpath open/reopen option
1129221167Sgnn */
1130221167Sgnn/* ARGSUSED */
1131221167Sgnnvoid
1132221167Sgnnvxge_rx_term(vxge_hal_vpath_h vpath_handle, vxge_hal_rxd_h rxdh,
1133221167Sgnn    void *dtr_priv, vxge_hal_rxd_state_e state, void *userdata,
1134221167Sgnn    vxge_hal_reopen_e reopen)
1135221167Sgnn{
1136221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
1137221167Sgnn	vxge_rxd_priv_t *rxd_priv = (vxge_rxd_priv_t *) dtr_priv;
1138221167Sgnn
1139221167Sgnn	if (state != VXGE_HAL_RXD_STATE_POSTED)
1140221167Sgnn		return;
1141221167Sgnn
1142221167Sgnn	if (rxd_priv != NULL) {
1143221167Sgnn		bus_dmamap_sync(vpath->dma_tag_rx, rxd_priv->dma_map,
1144221167Sgnn		    BUS_DMASYNC_POSTREAD);
1145221167Sgnn		bus_dmamap_unload(vpath->dma_tag_rx, rxd_priv->dma_map);
1146221167Sgnn		bus_dmamap_destroy(vpath->dma_tag_rx, rxd_priv->dma_map);
1147221167Sgnn
1148221167Sgnn		vxge_free_packet(rxd_priv->mbuf_pkt);
1149221167Sgnn	}
1150221167Sgnn	/* Free the descriptor */
1151221167Sgnn	vxge_hal_ring_rxd_free(vpath_handle, rxdh);
1152221167Sgnn}
1153221167Sgnn
1154221167Sgnn/*
1155221167Sgnn * vxge_rx_rxd_1b_get
1156221167Sgnn * Get descriptors of packet to send up
1157221167Sgnn */
1158221167Sgnnvoid
1159221167Sgnnvxge_rx_rxd_1b_get(vxge_vpath_t *vpath, vxge_hal_rxd_h rxdh, void *dtr_priv)
1160221167Sgnn{
1161221167Sgnn	vxge_rxd_priv_t *rxd_priv = (vxge_rxd_priv_t *) dtr_priv;
1162221167Sgnn	mbuf_t mbuf_up = rxd_priv->mbuf_pkt;
1163221167Sgnn
1164221167Sgnn	/* Retrieve data from completed descriptor */
1165221167Sgnn	vxge_hal_ring_rxd_1b_get(vpath->handle, rxdh, &rxd_priv->dma_addr[0],
1166221167Sgnn	    (u32 *) &rxd_priv->dma_sizes[0]);
1167221167Sgnn
1168221167Sgnn	/* Update newly created buffer to be sent up with packet length */
1169221167Sgnn	mbuf_up->m_len = rxd_priv->dma_sizes[0];
1170221167Sgnn	mbuf_up->m_pkthdr.len = rxd_priv->dma_sizes[0];
1171221167Sgnn	mbuf_up->m_next = NULL;
1172221167Sgnn}
1173221167Sgnn
1174221167Sgnn/*
1175221167Sgnn * vxge_rx_rxd_1b_set
1176221167Sgnn * Allocates new mbufs to be placed into descriptors
1177221167Sgnn */
1178221167Sgnnint
1179221167Sgnnvxge_rx_rxd_1b_set(vxge_vpath_t *vpath, vxge_hal_rxd_h rxdh, void *dtr_priv)
1180221167Sgnn{
1181221167Sgnn	int num_segs, err = 0;
1182221167Sgnn
1183221167Sgnn	mbuf_t mbuf_pkt;
1184221167Sgnn	bus_dmamap_t dma_map;
1185221167Sgnn	bus_dma_segment_t dma_buffers[1];
1186221167Sgnn	vxge_rxd_priv_t *rxd_priv = (vxge_rxd_priv_t *) dtr_priv;
1187221167Sgnn
1188221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
1189221167Sgnn
1190221167Sgnn	mbuf_pkt = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, vdev->rx_mbuf_sz);
1191221167Sgnn	if (!mbuf_pkt) {
1192221167Sgnn		err = ENOBUFS;
1193221167Sgnn		VXGE_DRV_STATS(vpath, rx_no_buf);
1194221167Sgnn		device_printf(vdev->ndev, "out of memory to allocate mbuf\n");
1195221167Sgnn		goto _exit0;
1196221167Sgnn	}
1197221167Sgnn
1198221167Sgnn	/* Update mbuf's length, packet length and receive interface */
1199221167Sgnn	mbuf_pkt->m_len = vdev->rx_mbuf_sz;
1200221167Sgnn	mbuf_pkt->m_pkthdr.len = vdev->rx_mbuf_sz;
1201221167Sgnn	mbuf_pkt->m_pkthdr.rcvif = vdev->ifp;
1202221167Sgnn
1203221167Sgnn	/* Load DMA map */
1204221167Sgnn	err = vxge_dma_mbuf_coalesce(vpath->dma_tag_rx, vpath->extra_dma_map,
1205221167Sgnn	    &mbuf_pkt, dma_buffers, &num_segs);
1206221167Sgnn	if (err != 0) {
1207221167Sgnn		VXGE_DRV_STATS(vpath, rx_map_fail);
1208221167Sgnn		vxge_free_packet(mbuf_pkt);
1209221167Sgnn		goto _exit0;
1210221167Sgnn	}
1211221167Sgnn
1212221167Sgnn	/* Unload DMA map of mbuf in current descriptor */
1213221167Sgnn	bus_dmamap_sync(vpath->dma_tag_rx, rxd_priv->dma_map,
1214221167Sgnn	    BUS_DMASYNC_POSTREAD);
1215221167Sgnn	bus_dmamap_unload(vpath->dma_tag_rx, rxd_priv->dma_map);
1216221167Sgnn
1217221167Sgnn	/* Update descriptor private data */
1218221167Sgnn	dma_map = rxd_priv->dma_map;
1219221167Sgnn	rxd_priv->mbuf_pkt = mbuf_pkt;
1220221167Sgnn	rxd_priv->dma_addr[0] = htole64(dma_buffers->ds_addr);
1221221167Sgnn	rxd_priv->dma_map = vpath->extra_dma_map;
1222221167Sgnn	vpath->extra_dma_map = dma_map;
1223221167Sgnn
1224221167Sgnn	/* Pre-Read/Write sync */
1225221167Sgnn	bus_dmamap_sync(vpath->dma_tag_rx, rxd_priv->dma_map,
1226221167Sgnn	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1227221167Sgnn
1228221167Sgnn	/* Set descriptor buffer */
1229221167Sgnn	vxge_hal_ring_rxd_1b_set(rxdh, rxd_priv->dma_addr[0], vdev->rx_mbuf_sz);
1230221167Sgnn
1231221167Sgnn_exit0:
1232221167Sgnn	return (err);
1233221167Sgnn}
1234221167Sgnn
1235221167Sgnn/*
1236221167Sgnn * vxge_link_up
1237221167Sgnn * Callback for Link-up indication from HAL
1238221167Sgnn */
1239221167Sgnn/* ARGSUSED */
1240221167Sgnnvoid
1241221167Sgnnvxge_link_up(vxge_hal_device_h devh, void *userdata)
1242221167Sgnn{
1243221167Sgnn	int i;
1244221167Sgnn	vxge_vpath_t *vpath;
1245221167Sgnn	vxge_hal_device_hw_info_t *hw_info;
1246221167Sgnn
1247221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) userdata;
1248221167Sgnn	hw_info = &vdev->config.hw_info;
1249221167Sgnn
1250221167Sgnn	ifnet_t ifp = vdev->ifp;
1251221167Sgnn
1252221167Sgnn	if (vdev->config.intr_mode == VXGE_HAL_INTR_MODE_MSIX) {
1253221167Sgnn		for (i = 0; i < vdev->no_of_vpath; i++) {
1254221167Sgnn			vpath = &(vdev->vpaths[i]);
1255221167Sgnn			vxge_hal_vpath_tti_ci_set(vpath->handle);
1256221167Sgnn			vxge_hal_vpath_rti_ci_set(vpath->handle);
1257221167Sgnn		}
1258221167Sgnn	}
1259221167Sgnn
1260221167Sgnn	if (vdev->is_privilaged && (hw_info->ports > 1)) {
1261221167Sgnn		vxge_active_port_update(vdev);
1262221167Sgnn		device_printf(vdev->ndev,
1263221167Sgnn		    "Active Port : %lld\n", vdev->active_port);
1264221167Sgnn	}
1265221167Sgnn
1266221167Sgnn	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1267221167Sgnn	if_link_state_change(ifp, LINK_STATE_UP);
1268221167Sgnn}
1269221167Sgnn
1270221167Sgnn/*
1271221167Sgnn * vxge_link_down
1272221167Sgnn * Callback for Link-down indication from HAL
1273221167Sgnn */
1274221167Sgnn/* ARGSUSED */
1275221167Sgnnvoid
1276221167Sgnnvxge_link_down(vxge_hal_device_h devh, void *userdata)
1277221167Sgnn{
1278221167Sgnn	int i;
1279221167Sgnn	vxge_vpath_t *vpath;
1280221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) userdata;
1281221167Sgnn
1282221167Sgnn	ifnet_t ifp = vdev->ifp;
1283221167Sgnn
1284221167Sgnn	if (vdev->config.intr_mode == VXGE_HAL_INTR_MODE_MSIX) {
1285221167Sgnn		for (i = 0; i < vdev->no_of_vpath; i++) {
1286221167Sgnn			vpath = &(vdev->vpaths[i]);
1287221167Sgnn			vxge_hal_vpath_tti_ci_reset(vpath->handle);
1288221167Sgnn			vxge_hal_vpath_rti_ci_reset(vpath->handle);
1289221167Sgnn		}
1290221167Sgnn	}
1291221167Sgnn
1292221167Sgnn	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1293221167Sgnn	if_link_state_change(ifp, LINK_STATE_DOWN);
1294221167Sgnn}
1295221167Sgnn
1296221167Sgnn/*
1297221167Sgnn * vxge_reset
1298221167Sgnn */
1299221167Sgnnvoid
1300221167Sgnnvxge_reset(vxge_dev_t *vdev)
1301221167Sgnn{
1302221167Sgnn	if (!vdev->is_initialized)
1303221167Sgnn		return;
1304221167Sgnn
1305221167Sgnn	VXGE_DRV_LOCK(vdev);
1306221167Sgnn	vxge_stop_locked(vdev);
1307221167Sgnn	vxge_init_locked(vdev);
1308221167Sgnn	VXGE_DRV_UNLOCK(vdev);
1309221167Sgnn}
1310221167Sgnn
1311221167Sgnn/*
1312221167Sgnn * vxge_crit_error
1313221167Sgnn * Callback for Critical error indication from HAL
1314221167Sgnn */
1315221167Sgnn/* ARGSUSED */
1316221167Sgnnvoid
1317221167Sgnnvxge_crit_error(vxge_hal_device_h devh, void *userdata,
1318221167Sgnn    vxge_hal_event_e type, u64 serr_data)
1319221167Sgnn{
1320221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) userdata;
1321221167Sgnn	ifnet_t ifp = vdev->ifp;
1322221167Sgnn
1323221167Sgnn	switch (type) {
1324221167Sgnn	case VXGE_HAL_EVENT_SERR:
1325221167Sgnn	case VXGE_HAL_EVENT_KDFCCTL:
1326221167Sgnn	case VXGE_HAL_EVENT_CRITICAL:
1327221167Sgnn		vxge_hal_device_intr_disable(vdev->devh);
1328221167Sgnn		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1329221167Sgnn		if_link_state_change(ifp, LINK_STATE_DOWN);
1330221167Sgnn		break;
1331221167Sgnn	default:
1332221167Sgnn		break;
1333221167Sgnn	}
1334221167Sgnn}
1335221167Sgnn
1336221167Sgnn/*
1337221167Sgnn * vxge_ifp_setup
1338221167Sgnn */
1339221167Sgnnint
1340221167Sgnnvxge_ifp_setup(device_t ndev)
1341221167Sgnn{
1342221167Sgnn	ifnet_t ifp;
1343221167Sgnn	int i, j, err = 0;
1344221167Sgnn
1345221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) device_get_softc(ndev);
1346221167Sgnn
1347221167Sgnn	for (i = 0, j = 0; i < VXGE_HAL_MAX_VIRTUAL_PATHS; i++) {
1348221167Sgnn		if (!bVAL1(vdev->config.hw_info.vpath_mask, i))
1349221167Sgnn			continue;
1350221167Sgnn
1351221167Sgnn		if (j >= vdev->no_of_vpath)
1352221167Sgnn			break;
1353221167Sgnn
1354221167Sgnn		vdev->vpaths[j].vp_id = i;
1355221167Sgnn		vdev->vpaths[j].vp_index = j;
1356221167Sgnn		vdev->vpaths[j].vdev = vdev;
1357221167Sgnn		vdev->vpaths[j].is_configured = TRUE;
1358221167Sgnn
1359221167Sgnn		vxge_os_memcpy((u8 *) vdev->vpaths[j].mac_addr,
1360221167Sgnn		    (u8 *) (vdev->config.hw_info.mac_addrs[i]),
1361221167Sgnn		    (size_t) ETHER_ADDR_LEN);
1362221167Sgnn		j++;
1363221167Sgnn	}
1364221167Sgnn
1365221167Sgnn	/* Get interface ifnet structure for this Ether device */
1366221167Sgnn	ifp = if_alloc(IFT_ETHER);
1367221167Sgnn	if (ifp == NULL) {
1368221167Sgnn		device_printf(vdev->ndev,
1369221167Sgnn		    "memory allocation for ifnet failed\n");
1370221167Sgnn		err = ENXIO;
1371221167Sgnn		goto _exit0;
1372221167Sgnn	}
1373221167Sgnn	vdev->ifp = ifp;
1374221167Sgnn
1375221167Sgnn	/* Initialize interface ifnet structure */
1376221167Sgnn	if_initname(ifp, device_get_name(ndev), device_get_unit(ndev));
1377221167Sgnn
1378221167Sgnn	ifp->if_mtu = ETHERMTU;
1379221167Sgnn	ifp->if_baudrate = VXGE_BAUDRATE;
1380221167Sgnn	ifp->if_init = vxge_init;
1381221167Sgnn	ifp->if_softc = vdev;
1382221167Sgnn	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1383221167Sgnn	ifp->if_ioctl = vxge_ioctl;
1384221167Sgnn	ifp->if_start = vxge_send;
1385221167Sgnn
1386221167Sgnn#if __FreeBSD_version >= 800000
1387221167Sgnn	ifp->if_transmit = vxge_mq_send;
1388221167Sgnn	ifp->if_qflush = vxge_mq_qflush;
1389221167Sgnn#endif
1390221167Sgnn	ifp->if_snd.ifq_drv_maxlen = max(vdev->config.ifq_maxlen, ifqmaxlen);
1391221167Sgnn	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
1392221167Sgnn	/* IFQ_SET_READY(&ifp->if_snd); */
1393221167Sgnn
1394221167Sgnn	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
1395221167Sgnn
1396221167Sgnn	ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
1397221167Sgnn	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
1398221167Sgnn	ifp->if_capabilities |= IFCAP_JUMBO_MTU;
1399221167Sgnn
1400221167Sgnn	if (vdev->config.tso_enable)
1401221167Sgnn		vxge_tso_config(vdev);
1402221167Sgnn
1403221167Sgnn	if (vdev->config.lro_enable)
1404221167Sgnn		ifp->if_capabilities |= IFCAP_LRO;
1405221167Sgnn
1406221167Sgnn	ifp->if_capenable = ifp->if_capabilities;
1407221167Sgnn
1408221167Sgnn	strlcpy(vdev->ndev_name, device_get_nameunit(ndev),
1409221167Sgnn	    sizeof(vdev->ndev_name));
1410221167Sgnn
1411221167Sgnn	/* Attach the interface */
1412221167Sgnn	ether_ifattach(ifp, vdev->vpaths[0].mac_addr);
1413221167Sgnn
1414221167Sgnn_exit0:
1415221167Sgnn	return (err);
1416221167Sgnn}
1417221167Sgnn
1418221167Sgnn/*
1419221167Sgnn * vxge_isr_setup
1420221167Sgnn * Register isr functions
1421221167Sgnn */
1422221167Sgnnint
1423221167Sgnnvxge_isr_setup(vxge_dev_t *vdev)
1424221167Sgnn{
1425221167Sgnn	int i, irq_rid, err = 0;
1426221167Sgnn	vxge_vpath_t *vpath;
1427221167Sgnn
1428221167Sgnn	void *isr_func_arg;
1429221167Sgnn	void (*isr_func_ptr) (void *);
1430221167Sgnn
1431221167Sgnn	switch (vdev->config.intr_mode) {
1432221167Sgnn	case VXGE_HAL_INTR_MODE_IRQLINE:
1433221167Sgnn		err = bus_setup_intr(vdev->ndev,
1434221167Sgnn		    vdev->config.isr_info[0].irq_res,
1435221167Sgnn		    (INTR_TYPE_NET | INTR_MPSAFE),
1436221167Sgnn		    vxge_isr_filter, vxge_isr_line, vdev,
1437221167Sgnn		    &vdev->config.isr_info[0].irq_handle);
1438221167Sgnn		break;
1439221167Sgnn
1440221167Sgnn	case VXGE_HAL_INTR_MODE_MSIX:
1441221167Sgnn		for (i = 0; i < vdev->intr_count; i++) {
1442221167Sgnn
1443221167Sgnn			irq_rid = vdev->config.isr_info[i].irq_rid;
1444221167Sgnn			vpath = &vdev->vpaths[irq_rid / 4];
1445221167Sgnn
1446221167Sgnn			if ((irq_rid % 4) == 2) {
1447221167Sgnn				isr_func_ptr = vxge_isr_msix;
1448221167Sgnn				isr_func_arg = (void *) vpath;
1449221167Sgnn			} else if ((irq_rid % 4) == 3) {
1450221167Sgnn				isr_func_ptr = vxge_isr_msix_alarm;
1451221167Sgnn				isr_func_arg = (void *) vpath;
1452221167Sgnn			} else
1453221167Sgnn				break;
1454221167Sgnn
1455221167Sgnn			err = bus_setup_intr(vdev->ndev,
1456221167Sgnn			    vdev->config.isr_info[i].irq_res,
1457221167Sgnn			    (INTR_TYPE_NET | INTR_MPSAFE), NULL,
1458221167Sgnn			    (void *) isr_func_ptr, (void *) isr_func_arg,
1459221167Sgnn			    &vdev->config.isr_info[i].irq_handle);
1460221167Sgnn			if (err != 0)
1461221167Sgnn				break;
1462221167Sgnn		}
1463221167Sgnn
1464221167Sgnn		if (err != 0) {
1465221167Sgnn			/* Teardown interrupt handler */
1466221167Sgnn			while (--i > 0)
1467221167Sgnn				bus_teardown_intr(vdev->ndev,
1468221167Sgnn				    vdev->config.isr_info[i].irq_res,
1469221167Sgnn				    vdev->config.isr_info[i].irq_handle);
1470221167Sgnn		}
1471221167Sgnn		break;
1472221167Sgnn	}
1473221167Sgnn
1474221167Sgnn	return (err);
1475221167Sgnn}
1476221167Sgnn
1477221167Sgnn/*
1478221167Sgnn * vxge_isr_filter
1479221167Sgnn * ISR filter function - filter interrupts from other shared devices
1480221167Sgnn */
1481221167Sgnnint
1482221167Sgnnvxge_isr_filter(void *handle)
1483221167Sgnn{
1484221167Sgnn	u64 val64 = 0;
1485221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) handle;
1486221167Sgnn	__hal_device_t *hldev = (__hal_device_t *) vdev->devh;
1487221167Sgnn
1488221167Sgnn	vxge_hal_common_reg_t *common_reg =
1489221167Sgnn	(vxge_hal_common_reg_t *) (hldev->common_reg);
1490221167Sgnn
1491221167Sgnn	val64 = vxge_os_pio_mem_read64(vdev->pdev, (vdev->devh)->regh0,
1492221167Sgnn	    &common_reg->titan_general_int_status);
1493221167Sgnn
1494221167Sgnn	return ((val64) ? FILTER_SCHEDULE_THREAD : FILTER_STRAY);
1495221167Sgnn}
1496221167Sgnn
1497221167Sgnn/*
1498221167Sgnn * vxge_isr_line
1499221167Sgnn * Interrupt service routine for Line interrupts
1500221167Sgnn */
1501221167Sgnnvoid
1502221167Sgnnvxge_isr_line(void *vdev_ptr)
1503221167Sgnn{
1504221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) vdev_ptr;
1505221167Sgnn
1506221167Sgnn	vxge_hal_device_handle_irq(vdev->devh, 0);
1507221167Sgnn}
1508221167Sgnn
1509221167Sgnnvoid
1510221167Sgnnvxge_isr_msix(void *vpath_ptr)
1511221167Sgnn{
1512221167Sgnn	u32 got_rx = 0;
1513221167Sgnn	u32 got_tx = 0;
1514221167Sgnn
1515221167Sgnn	__hal_virtualpath_t *hal_vpath;
1516221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) vpath_ptr;
1517221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
1518221167Sgnn	hal_vpath = ((__hal_vpath_handle_t *) vpath->handle)->vpath;
1519221167Sgnn
1520221167Sgnn	VXGE_DRV_STATS(vpath, isr_msix);
1521221167Sgnn	VXGE_HAL_DEVICE_STATS_SW_INFO_TRAFFIC_INTR(vdev->devh);
1522221167Sgnn
1523221167Sgnn	vxge_hal_vpath_mf_msix_mask(vpath->handle, vpath->msix_vec);
1524221167Sgnn
1525221167Sgnn	/* processing rx */
1526221167Sgnn	vxge_hal_vpath_poll_rx(vpath->handle, &got_rx);
1527221167Sgnn
1528221167Sgnn	/* processing tx */
1529221167Sgnn	if (hal_vpath->vp_config->fifo.enable) {
1530221167Sgnn		vxge_intr_coalesce_tx(vpath);
1531221167Sgnn		vxge_hal_vpath_poll_tx(vpath->handle, &got_tx);
1532221167Sgnn	}
1533221167Sgnn
1534221167Sgnn	vxge_hal_vpath_mf_msix_unmask(vpath->handle, vpath->msix_vec);
1535221167Sgnn}
1536221167Sgnn
1537221167Sgnnvoid
1538221167Sgnnvxge_isr_msix_alarm(void *vpath_ptr)
1539221167Sgnn{
1540221167Sgnn	int i;
1541221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
1542221167Sgnn
1543221167Sgnn	vxge_vpath_t *vpath = (vxge_vpath_t *) vpath_ptr;
1544221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
1545221167Sgnn
1546221167Sgnn	VXGE_HAL_DEVICE_STATS_SW_INFO_NOT_TRAFFIC_INTR(vdev->devh);
1547221167Sgnn
1548221167Sgnn	/* Process alarms in each vpath */
1549221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
1550221167Sgnn
1551221167Sgnn		vpath = &(vdev->vpaths[i]);
1552221167Sgnn		vxge_hal_vpath_mf_msix_mask(vpath->handle,
1553221167Sgnn		    vpath->msix_vec_alarm);
1554221167Sgnn		status = vxge_hal_vpath_alarm_process(vpath->handle, 0);
1555221167Sgnn		if ((status == VXGE_HAL_ERR_EVENT_SLOT_FREEZE) ||
1556221167Sgnn		    (status == VXGE_HAL_ERR_EVENT_SERR)) {
1557221167Sgnn			device_printf(vdev->ndev,
1558221167Sgnn			    "processing alarms urecoverable error %x\n",
1559221167Sgnn			    status);
1560221167Sgnn
1561221167Sgnn			/* Stop the driver */
1562221167Sgnn			vdev->is_initialized = FALSE;
1563221167Sgnn			break;
1564221167Sgnn		}
1565221167Sgnn		vxge_hal_vpath_mf_msix_unmask(vpath->handle,
1566221167Sgnn		    vpath->msix_vec_alarm);
1567221167Sgnn	}
1568221167Sgnn}
1569221167Sgnn
1570221167Sgnn/*
1571221167Sgnn * vxge_msix_enable
1572221167Sgnn */
1573221167Sgnnvxge_hal_status_e
1574221167Sgnnvxge_msix_enable(vxge_dev_t *vdev)
1575221167Sgnn{
1576221167Sgnn	int i, first_vp_id, msix_id;
1577221167Sgnn
1578221167Sgnn	vxge_vpath_t *vpath;
1579221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
1580221167Sgnn
1581221167Sgnn	/*
1582221167Sgnn	 * Unmasking and Setting MSIX vectors before enabling interrupts
1583221167Sgnn	 * tim[] : 0 - Tx ## 1 - Rx ## 2 - UMQ-DMQ ## 0 - BITMAP
1584221167Sgnn	 */
1585221167Sgnn	int tim[4] = {0, 1, 0, 0};
1586221167Sgnn
1587221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
1588221167Sgnn
1589221167Sgnn		vpath = vdev->vpaths + i;
1590221167Sgnn		first_vp_id = vdev->vpaths[0].vp_id;
1591221167Sgnn
1592221167Sgnn		msix_id = vpath->vp_id * VXGE_HAL_VPATH_MSIX_ACTIVE;
1593221167Sgnn		tim[1] = vpath->msix_vec = msix_id + 1;
1594221167Sgnn
1595221167Sgnn		vpath->msix_vec_alarm = first_vp_id *
1596221167Sgnn		    VXGE_HAL_VPATH_MSIX_ACTIVE + VXGE_HAL_VPATH_MSIX_ALARM_ID;
1597221167Sgnn
1598221167Sgnn		status = vxge_hal_vpath_mf_msix_set(vpath->handle,
1599221167Sgnn		    tim, VXGE_HAL_VPATH_MSIX_ALARM_ID);
1600221167Sgnn
1601221167Sgnn		if (status != VXGE_HAL_OK) {
1602221167Sgnn			device_printf(vdev->ndev,
1603221167Sgnn			    "failed to set msix vectors to vpath\n");
1604221167Sgnn			break;
1605221167Sgnn		}
1606221167Sgnn
1607221167Sgnn		vxge_hal_vpath_mf_msix_unmask(vpath->handle, vpath->msix_vec);
1608221167Sgnn		vxge_hal_vpath_mf_msix_unmask(vpath->handle,
1609221167Sgnn		    vpath->msix_vec_alarm);
1610221167Sgnn	}
1611221167Sgnn
1612221167Sgnn	return (status);
1613221167Sgnn}
1614221167Sgnn
1615221167Sgnn/*
1616221167Sgnn * vxge_media_init
1617221167Sgnn * Initializes, adds and sets media
1618221167Sgnn */
1619221167Sgnnvoid
1620221167Sgnnvxge_media_init(vxge_dev_t *vdev)
1621221167Sgnn{
1622221167Sgnn	ifmedia_init(&vdev->media,
1623221167Sgnn	    IFM_IMASK, vxge_media_change, vxge_media_status);
1624221167Sgnn
1625221167Sgnn	/* Add supported media */
1626221167Sgnn	ifmedia_add(&vdev->media,
1627221167Sgnn	    IFM_ETHER | vdev->ifm_optics | IFM_FDX,
1628221167Sgnn	    0, NULL);
1629221167Sgnn
1630221167Sgnn	/* Set media */
1631221167Sgnn	ifmedia_add(&vdev->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1632221167Sgnn	ifmedia_set(&vdev->media, IFM_ETHER | IFM_AUTO);
1633221167Sgnn}
1634221167Sgnn
1635221167Sgnn/*
1636221167Sgnn * vxge_media_status
1637221167Sgnn * Callback  for interface media settings
1638221167Sgnn */
1639221167Sgnnvoid
1640221167Sgnnvxge_media_status(ifnet_t ifp, struct ifmediareq *ifmr)
1641221167Sgnn{
1642221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) ifp->if_softc;
1643221167Sgnn	vxge_hal_device_t *hldev = vdev->devh;
1644221167Sgnn
1645221167Sgnn	ifmr->ifm_status = IFM_AVALID;
1646221167Sgnn	ifmr->ifm_active = IFM_ETHER;
1647221167Sgnn
1648221167Sgnn	/* set link state */
1649221167Sgnn	if (vxge_hal_device_link_state_get(hldev) == VXGE_HAL_LINK_UP) {
1650221167Sgnn		ifmr->ifm_status |= IFM_ACTIVE;
1651221167Sgnn		ifmr->ifm_active |= vdev->ifm_optics | IFM_FDX;
1652221167Sgnn		if_link_state_change(ifp, LINK_STATE_UP);
1653221167Sgnn	}
1654221167Sgnn}
1655221167Sgnn
1656221167Sgnn/*
1657221167Sgnn * vxge_media_change
1658221167Sgnn * Media change driver callback
1659221167Sgnn */
1660221167Sgnnint
1661221167Sgnnvxge_media_change(ifnet_t ifp)
1662221167Sgnn{
1663221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) ifp->if_softc;
1664221167Sgnn	struct ifmedia *ifmediap = &vdev->media;
1665221167Sgnn
1666221167Sgnn	return (IFM_TYPE(ifmediap->ifm_media) != IFM_ETHER ? EINVAL : 0);
1667221167Sgnn}
1668221167Sgnn
1669221167Sgnn/*
1670221167Sgnn * Allocate PCI resources
1671221167Sgnn */
1672221167Sgnnint
1673221167Sgnnvxge_alloc_resources(vxge_dev_t *vdev)
1674221167Sgnn{
1675221167Sgnn	int err = 0;
1676221167Sgnn	vxge_pci_info_t *pci_info = NULL;
1677221167Sgnn	vxge_free_resources_e error_level = VXGE_FREE_NONE;
1678221167Sgnn
1679221167Sgnn	device_t ndev = vdev->ndev;
1680221167Sgnn
1681221167Sgnn	/* Allocate Buffer for HAL Device Configuration */
1682221167Sgnn	vdev->device_config = (vxge_hal_device_config_t *)
1683221167Sgnn	    vxge_mem_alloc(sizeof(vxge_hal_device_config_t));
1684221167Sgnn
1685221167Sgnn	if (!vdev->device_config) {
1686221167Sgnn		err = ENOMEM;
1687221167Sgnn		error_level = VXGE_DISABLE_PCI_BUSMASTER;
1688221167Sgnn		device_printf(vdev->ndev,
1689221167Sgnn		    "failed to allocate memory for device config\n");
1690221167Sgnn		goto _exit0;
1691221167Sgnn	}
1692221167Sgnn
1693221167Sgnn
1694221167Sgnn	pci_info = (vxge_pci_info_t *) vxge_mem_alloc(sizeof(vxge_pci_info_t));
1695221167Sgnn	if (!pci_info) {
1696221167Sgnn		error_level = VXGE_FREE_DEVICE_CONFIG;
1697221167Sgnn		err = ENOMEM;
1698221167Sgnn		device_printf(vdev->ndev,
1699221167Sgnn		    "failed to allocate memory for pci info\n");
1700221167Sgnn		goto _exit0;
1701221167Sgnn	}
1702221167Sgnn	pci_info->ndev = ndev;
1703221167Sgnn	vdev->pdev = pci_info;
1704221167Sgnn
1705221167Sgnn	err = vxge_alloc_bar_resources(vdev, 0);
1706221167Sgnn	if (err != 0) {
1707221167Sgnn		error_level = VXGE_FREE_BAR0;
1708221167Sgnn		goto _exit0;
1709221167Sgnn	}
1710221167Sgnn
1711221167Sgnn	err = vxge_alloc_bar_resources(vdev, 1);
1712221167Sgnn	if (err != 0) {
1713221167Sgnn		error_level = VXGE_FREE_BAR1;
1714221167Sgnn		goto _exit0;
1715221167Sgnn	}
1716221167Sgnn
1717221167Sgnn	err = vxge_alloc_bar_resources(vdev, 2);
1718221167Sgnn	if (err != 0)
1719221167Sgnn		error_level = VXGE_FREE_BAR2;
1720221167Sgnn
1721221167Sgnn_exit0:
1722221167Sgnn	if (error_level)
1723221167Sgnn		vxge_free_resources(ndev, error_level);
1724221167Sgnn
1725221167Sgnn	return (err);
1726221167Sgnn}
1727221167Sgnn
1728221167Sgnn/*
1729221167Sgnn * vxge_alloc_bar_resources
1730221167Sgnn * Allocates BAR resources
1731221167Sgnn */
1732221167Sgnnint
1733221167Sgnnvxge_alloc_bar_resources(vxge_dev_t *vdev, int i)
1734221167Sgnn{
1735221167Sgnn	int err = 0;
1736221167Sgnn	int res_id = 0;
1737221167Sgnn	vxge_pci_info_t *pci_info = vdev->pdev;
1738221167Sgnn
1739221167Sgnn	res_id = PCIR_BAR((i == 0) ? 0 : (i * 2));
1740221167Sgnn
1741221167Sgnn	pci_info->bar_info[i] =
1742221167Sgnn	    bus_alloc_resource_any(vdev->ndev,
1743221167Sgnn	    SYS_RES_MEMORY, &res_id, RF_ACTIVE);
1744221167Sgnn
1745221167Sgnn	if (pci_info->bar_info[i] == NULL) {
1746221167Sgnn		device_printf(vdev->ndev,
1747221167Sgnn		    "failed to allocate memory for bus resources\n");
1748221167Sgnn		err = ENOMEM;
1749221167Sgnn		goto _exit0;
1750221167Sgnn	}
1751221167Sgnn
1752221167Sgnn	pci_info->reg_map[i] =
1753221167Sgnn	    (vxge_bus_res_t *) vxge_mem_alloc(sizeof(vxge_bus_res_t));
1754221167Sgnn
1755221167Sgnn	if (pci_info->reg_map[i] == NULL) {
1756221167Sgnn		device_printf(vdev->ndev,
1757221167Sgnn		    "failed to allocate memory bar resources\n");
1758221167Sgnn		err = ENOMEM;
1759221167Sgnn		goto _exit0;
1760221167Sgnn	}
1761221167Sgnn
1762221167Sgnn	((vxge_bus_res_t *) (pci_info->reg_map[i]))->bus_space_tag =
1763221167Sgnn	    rman_get_bustag(pci_info->bar_info[i]);
1764221167Sgnn
1765221167Sgnn	((vxge_bus_res_t *) (pci_info->reg_map[i]))->bus_space_handle =
1766221167Sgnn	    rman_get_bushandle(pci_info->bar_info[i]);
1767221167Sgnn
1768221167Sgnn	((vxge_bus_res_t *) (pci_info->reg_map[i]))->bar_start_addr =
1769221167Sgnn	    pci_info->bar_info[i];
1770221167Sgnn
1771221167Sgnn	((vxge_bus_res_t *) (pci_info->reg_map[i]))->bus_res_len =
1772221167Sgnn	    rman_get_size(pci_info->bar_info[i]);
1773221167Sgnn
1774221167Sgnn_exit0:
1775221167Sgnn	return (err);
1776221167Sgnn}
1777221167Sgnn
1778221167Sgnn/*
1779221167Sgnn * vxge_alloc_isr_resources
1780221167Sgnn */
1781221167Sgnnint
1782221167Sgnnvxge_alloc_isr_resources(vxge_dev_t *vdev)
1783221167Sgnn{
1784221167Sgnn	int i, err = 0, irq_rid;
1785221167Sgnn	int msix_vec_reqd, intr_count, msix_count;
1786221167Sgnn
1787221167Sgnn	int intr_mode = VXGE_HAL_INTR_MODE_IRQLINE;
1788221167Sgnn
1789221167Sgnn	if (vdev->config.intr_mode == VXGE_HAL_INTR_MODE_MSIX) {
1790221167Sgnn		/* MSI-X messages supported by device */
1791221167Sgnn		intr_count = pci_msix_count(vdev->ndev);
1792221167Sgnn		if (intr_count) {
1793221167Sgnn
1794221167Sgnn			msix_vec_reqd = 4 * vdev->no_of_vpath;
1795221167Sgnn			if (intr_count >= msix_vec_reqd) {
1796221167Sgnn				intr_count = msix_vec_reqd;
1797221167Sgnn
1798221167Sgnn				err = pci_alloc_msix(vdev->ndev, &intr_count);
1799221167Sgnn				if (err == 0)
1800221167Sgnn					intr_mode = VXGE_HAL_INTR_MODE_MSIX;
1801221167Sgnn			}
1802221167Sgnn
1803221167Sgnn			if ((err != 0) || (intr_count < msix_vec_reqd)) {
1804221167Sgnn				device_printf(vdev->ndev, "Unable to allocate "
1805221167Sgnn				    "msi/x vectors switching to INTA mode\n");
1806221167Sgnn			}
1807221167Sgnn		}
1808221167Sgnn	}
1809221167Sgnn
1810221167Sgnn	err = 0;
1811221167Sgnn	vdev->intr_count = 0;
1812221167Sgnn	vdev->config.intr_mode = intr_mode;
1813221167Sgnn
1814221167Sgnn	switch (vdev->config.intr_mode) {
1815221167Sgnn	case VXGE_HAL_INTR_MODE_IRQLINE:
1816221167Sgnn		vdev->config.isr_info[0].irq_rid = 0;
1817221167Sgnn		vdev->config.isr_info[0].irq_res =
1818221167Sgnn		    bus_alloc_resource_any(vdev->ndev, SYS_RES_IRQ,
1819221167Sgnn		    &vdev->config.isr_info[0].irq_rid,
1820221167Sgnn		    (RF_SHAREABLE | RF_ACTIVE));
1821221167Sgnn
1822221167Sgnn		if (vdev->config.isr_info[0].irq_res == NULL) {
1823221167Sgnn			device_printf(vdev->ndev,
1824221167Sgnn			    "failed to allocate line interrupt resource\n");
1825221167Sgnn			err = ENOMEM;
1826221167Sgnn			goto _exit0;
1827221167Sgnn		}
1828221167Sgnn		vdev->intr_count++;
1829221167Sgnn		break;
1830221167Sgnn
1831221167Sgnn	case VXGE_HAL_INTR_MODE_MSIX:
1832221167Sgnn		msix_count = 0;
1833221167Sgnn		for (i = 0; i < vdev->no_of_vpath; i++) {
1834221167Sgnn			irq_rid = i * 4;
1835221167Sgnn
1836221167Sgnn			vdev->config.isr_info[msix_count].irq_rid = irq_rid + 2;
1837221167Sgnn			vdev->config.isr_info[msix_count].irq_res =
1838221167Sgnn			    bus_alloc_resource_any(vdev->ndev, SYS_RES_IRQ,
1839221167Sgnn			    &vdev->config.isr_info[msix_count].irq_rid,
1840221167Sgnn			    (RF_SHAREABLE | RF_ACTIVE));
1841221167Sgnn
1842221167Sgnn			if (vdev->config.isr_info[msix_count].irq_res == NULL) {
1843221167Sgnn				device_printf(vdev->ndev,
1844221167Sgnn				    "allocating bus resource (rid %d) failed\n",
1845221167Sgnn				    vdev->config.isr_info[msix_count].irq_rid);
1846221167Sgnn				err = ENOMEM;
1847221167Sgnn				goto _exit0;
1848221167Sgnn			}
1849221167Sgnn
1850221167Sgnn			vdev->intr_count++;
1851221167Sgnn			err = bus_bind_intr(vdev->ndev,
1852221167Sgnn			    vdev->config.isr_info[msix_count].irq_res,
1853221167Sgnn			    (i % mp_ncpus));
1854221167Sgnn			if (err != 0)
1855221167Sgnn				break;
1856221167Sgnn
1857221167Sgnn			msix_count++;
1858221167Sgnn		}
1859221167Sgnn
1860221167Sgnn		vdev->config.isr_info[msix_count].irq_rid = 3;
1861221167Sgnn		vdev->config.isr_info[msix_count].irq_res =
1862221167Sgnn		    bus_alloc_resource_any(vdev->ndev, SYS_RES_IRQ,
1863221167Sgnn		    &vdev->config.isr_info[msix_count].irq_rid,
1864221167Sgnn		    (RF_SHAREABLE | RF_ACTIVE));
1865221167Sgnn
1866221167Sgnn		if (vdev->config.isr_info[msix_count].irq_res == NULL) {
1867221167Sgnn			device_printf(vdev->ndev,
1868221167Sgnn			    "allocating bus resource (rid %d) failed\n",
1869221167Sgnn			    vdev->config.isr_info[msix_count].irq_rid);
1870221167Sgnn			err = ENOMEM;
1871221167Sgnn			goto _exit0;
1872221167Sgnn		}
1873221167Sgnn
1874221167Sgnn		vdev->intr_count++;
1875221167Sgnn		err = bus_bind_intr(vdev->ndev,
1876221167Sgnn		    vdev->config.isr_info[msix_count].irq_res, (i % mp_ncpus));
1877221167Sgnn
1878221167Sgnn		break;
1879221167Sgnn	}
1880221167Sgnn
1881221167Sgnn	vdev->device_config->intr_mode = vdev->config.intr_mode;
1882221167Sgnn
1883221167Sgnn_exit0:
1884221167Sgnn	return (err);
1885221167Sgnn}
1886221167Sgnn
1887221167Sgnn/*
1888221167Sgnn * vxge_free_resources
1889221167Sgnn * Undo what-all we did during load/attach
1890221167Sgnn */
1891221167Sgnnvoid
1892221167Sgnnvxge_free_resources(device_t ndev, vxge_free_resources_e vxge_free_resource)
1893221167Sgnn{
1894221167Sgnn	int i;
1895221167Sgnn	vxge_dev_t *vdev;
1896221167Sgnn
1897221167Sgnn	vdev = (vxge_dev_t *) device_get_softc(ndev);
1898221167Sgnn
1899221167Sgnn	switch (vxge_free_resource) {
1900221167Sgnn	case VXGE_FREE_ALL:
1901221167Sgnn		for (i = 0; i < vdev->intr_count; i++) {
1902221167Sgnn			bus_teardown_intr(ndev,
1903221167Sgnn			    vdev->config.isr_info[i].irq_res,
1904221167Sgnn			    vdev->config.isr_info[i].irq_handle);
1905221167Sgnn		}
1906221167Sgnn		/* FALLTHROUGH */
1907221167Sgnn
1908221167Sgnn	case VXGE_FREE_INTERFACE:
1909221167Sgnn		ether_ifdetach(vdev->ifp);
1910221167Sgnn		bus_generic_detach(ndev);
1911221167Sgnn		if_free(vdev->ifp);
1912221167Sgnn		/* FALLTHROUGH */
1913221167Sgnn
1914221167Sgnn	case VXGE_FREE_MEDIA:
1915221167Sgnn		ifmedia_removeall(&vdev->media);
1916221167Sgnn		/* FALLTHROUGH */
1917221167Sgnn
1918221167Sgnn	case VXGE_FREE_MUTEX:
1919221167Sgnn		vxge_mutex_destroy(vdev);
1920221167Sgnn		/* FALLTHROUGH */
1921221167Sgnn
1922221167Sgnn	case VXGE_FREE_VPATH:
1923221167Sgnn		vxge_mem_free(vdev->vpaths,
1924221167Sgnn		    vdev->no_of_vpath * sizeof(vxge_vpath_t));
1925221167Sgnn		/* FALLTHROUGH */
1926221167Sgnn
1927221167Sgnn	case VXGE_FREE_TERMINATE_DEVICE:
1928221167Sgnn		if (vdev->devh != NULL) {
1929221167Sgnn			vxge_hal_device_private_set(vdev->devh, 0);
1930221167Sgnn			vxge_hal_device_terminate(vdev->devh);
1931221167Sgnn		}
1932221167Sgnn		/* FALLTHROUGH */
1933221167Sgnn
1934221167Sgnn	case VXGE_FREE_ISR_RESOURCE:
1935221167Sgnn		vxge_free_isr_resources(vdev);
1936221167Sgnn		/* FALLTHROUGH */
1937221167Sgnn
1938221167Sgnn	case VXGE_FREE_BAR2:
1939221167Sgnn		vxge_free_bar_resources(vdev, 2);
1940221167Sgnn		/* FALLTHROUGH */
1941221167Sgnn
1942221167Sgnn	case VXGE_FREE_BAR1:
1943221167Sgnn		vxge_free_bar_resources(vdev, 1);
1944221167Sgnn		/* FALLTHROUGH */
1945221167Sgnn
1946221167Sgnn	case VXGE_FREE_BAR0:
1947221167Sgnn		vxge_free_bar_resources(vdev, 0);
1948221167Sgnn		/* FALLTHROUGH */
1949221167Sgnn
1950221167Sgnn	case VXGE_FREE_PCI_INFO:
1951221167Sgnn		vxge_mem_free(vdev->pdev, sizeof(vxge_pci_info_t));
1952221167Sgnn		/* FALLTHROUGH */
1953221167Sgnn
1954221167Sgnn	case VXGE_FREE_DEVICE_CONFIG:
1955221167Sgnn		vxge_mem_free(vdev->device_config,
1956221167Sgnn		    sizeof(vxge_hal_device_config_t));
1957221167Sgnn		/* FALLTHROUGH */
1958221167Sgnn
1959221167Sgnn	case VXGE_DISABLE_PCI_BUSMASTER:
1960221167Sgnn		pci_disable_busmaster(ndev);
1961221167Sgnn		/* FALLTHROUGH */
1962221167Sgnn
1963221167Sgnn	case VXGE_FREE_TERMINATE_DRIVER:
1964221167Sgnn		if (vxge_dev_ref_count) {
1965221167Sgnn			--vxge_dev_ref_count;
1966221167Sgnn			if (0 == vxge_dev_ref_count)
1967221167Sgnn				vxge_hal_driver_terminate();
1968221167Sgnn		}
1969221167Sgnn		/* FALLTHROUGH */
1970221167Sgnn
1971221167Sgnn	default:
1972221167Sgnn	case VXGE_FREE_NONE:
1973221167Sgnn		break;
1974221167Sgnn		/* NOTREACHED */
1975221167Sgnn	}
1976221167Sgnn}
1977221167Sgnn
1978221167Sgnnvoid
1979221167Sgnnvxge_free_isr_resources(vxge_dev_t *vdev)
1980221167Sgnn{
1981221167Sgnn	int i;
1982221167Sgnn
1983221167Sgnn	switch (vdev->config.intr_mode) {
1984221167Sgnn	case VXGE_HAL_INTR_MODE_IRQLINE:
1985221167Sgnn		if (vdev->config.isr_info[0].irq_res) {
1986221167Sgnn			bus_release_resource(vdev->ndev, SYS_RES_IRQ,
1987221167Sgnn			    vdev->config.isr_info[0].irq_rid,
1988221167Sgnn			    vdev->config.isr_info[0].irq_res);
1989221167Sgnn
1990221167Sgnn			vdev->config.isr_info[0].irq_res = NULL;
1991221167Sgnn		}
1992221167Sgnn		break;
1993221167Sgnn
1994221167Sgnn	case VXGE_HAL_INTR_MODE_MSIX:
1995221167Sgnn		for (i = 0; i < vdev->intr_count; i++) {
1996221167Sgnn			if (vdev->config.isr_info[i].irq_res) {
1997221167Sgnn				bus_release_resource(vdev->ndev, SYS_RES_IRQ,
1998221167Sgnn				    vdev->config.isr_info[i].irq_rid,
1999221167Sgnn				    vdev->config.isr_info[i].irq_res);
2000221167Sgnn
2001221167Sgnn				vdev->config.isr_info[i].irq_res = NULL;
2002221167Sgnn			}
2003221167Sgnn		}
2004221167Sgnn
2005221167Sgnn		if (vdev->intr_count)
2006221167Sgnn			pci_release_msi(vdev->ndev);
2007221167Sgnn
2008221167Sgnn		break;
2009221167Sgnn	}
2010221167Sgnn}
2011221167Sgnn
2012221167Sgnnvoid
2013221167Sgnnvxge_free_bar_resources(vxge_dev_t *vdev, int i)
2014221167Sgnn{
2015221167Sgnn	int res_id = 0;
2016221167Sgnn	vxge_pci_info_t *pci_info = vdev->pdev;
2017221167Sgnn
2018221167Sgnn	res_id = PCIR_BAR((i == 0) ? 0 : (i * 2));
2019221167Sgnn
2020221167Sgnn	if (pci_info->bar_info[i])
2021221167Sgnn		bus_release_resource(vdev->ndev, SYS_RES_MEMORY,
2022221167Sgnn		    res_id, pci_info->bar_info[i]);
2023221167Sgnn
2024221167Sgnn	vxge_mem_free(pci_info->reg_map[i], sizeof(vxge_bus_res_t));
2025221167Sgnn}
2026221167Sgnn
2027221167Sgnn/*
2028221167Sgnn * vxge_init_mutex
2029221167Sgnn * Initializes mutexes used in driver
2030221167Sgnn */
2031221167Sgnnvoid
2032221167Sgnnvxge_mutex_init(vxge_dev_t *vdev)
2033221167Sgnn{
2034221167Sgnn	int i;
2035221167Sgnn
2036221167Sgnn	snprintf(vdev->mtx_drv_name, sizeof(vdev->mtx_drv_name),
2037221167Sgnn	    "%s_drv", vdev->ndev_name);
2038221167Sgnn
2039221167Sgnn	mtx_init(&vdev->mtx_drv, vdev->mtx_drv_name,
2040221167Sgnn	    MTX_NETWORK_LOCK, MTX_DEF);
2041221167Sgnn
2042221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
2043221167Sgnn		snprintf(vdev->vpaths[i].mtx_tx_name,
2044221167Sgnn		    sizeof(vdev->vpaths[i].mtx_tx_name), "%s_tx_%d",
2045221167Sgnn		    vdev->ndev_name, i);
2046221167Sgnn
2047221167Sgnn		mtx_init(&vdev->vpaths[i].mtx_tx,
2048221167Sgnn		    vdev->vpaths[i].mtx_tx_name, NULL, MTX_DEF);
2049221167Sgnn	}
2050221167Sgnn}
2051221167Sgnn
2052221167Sgnn/*
2053221167Sgnn * vxge_mutex_destroy
2054221167Sgnn * Destroys mutexes used in driver
2055221167Sgnn */
2056221167Sgnnvoid
2057221167Sgnnvxge_mutex_destroy(vxge_dev_t *vdev)
2058221167Sgnn{
2059221167Sgnn	int i;
2060221167Sgnn
2061221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++)
2062221167Sgnn		VXGE_TX_LOCK_DESTROY(&(vdev->vpaths[i]));
2063221167Sgnn
2064221167Sgnn	VXGE_DRV_LOCK_DESTROY(vdev);
2065221167Sgnn}
2066221167Sgnn
2067221167Sgnn/*
2068221167Sgnn * vxge_rth_config
2069221167Sgnn */
2070221167Sgnnvxge_hal_status_e
2071221167Sgnnvxge_rth_config(vxge_dev_t *vdev)
2072221167Sgnn{
2073221167Sgnn	int i;
2074221167Sgnn	vxge_hal_vpath_h vpath_handle;
2075221167Sgnn	vxge_hal_rth_hash_types_t hash_types;
2076221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
2077221167Sgnn	u8 mtable[256] = {0};
2078221167Sgnn
2079221167Sgnn	/* Filling matable with bucket-to-vpath mapping */
2080221167Sgnn	vdev->config.rth_bkt_sz = VXGE_DEFAULT_RTH_BUCKET_SIZE;
2081221167Sgnn
2082221167Sgnn	for (i = 0; i < (1 << vdev->config.rth_bkt_sz); i++)
2083221167Sgnn		mtable[i] = i % vdev->no_of_vpath;
2084221167Sgnn
2085221167Sgnn	/* Fill RTH hash types */
2086221167Sgnn	hash_types.hash_type_tcpipv4_en = VXGE_HAL_RING_HASH_TYPE_TCP_IPV4;
2087221167Sgnn	hash_types.hash_type_tcpipv6_en = VXGE_HAL_RING_HASH_TYPE_TCP_IPV6;
2088221167Sgnn	hash_types.hash_type_tcpipv6ex_en = VXGE_HAL_RING_HASH_TYPE_TCP_IPV6_EX;
2089221167Sgnn	hash_types.hash_type_ipv4_en = VXGE_HAL_RING_HASH_TYPE_IPV4;
2090221167Sgnn	hash_types.hash_type_ipv6_en = VXGE_HAL_RING_HASH_TYPE_IPV6;
2091221167Sgnn	hash_types.hash_type_ipv6ex_en = VXGE_HAL_RING_HASH_TYPE_IPV6_EX;
2092221167Sgnn
2093221167Sgnn	/* set indirection table, bucket-to-vpath mapping */
2094221167Sgnn	status = vxge_hal_vpath_rts_rth_itable_set(vdev->vpath_handles,
2095221167Sgnn	    vdev->no_of_vpath, mtable,
2096221167Sgnn	    ((u32) (1 << vdev->config.rth_bkt_sz)));
2097221167Sgnn
2098221167Sgnn	if (status != VXGE_HAL_OK) {
2099221167Sgnn		device_printf(vdev->ndev, "rth configuration failed\n");
2100221167Sgnn		goto _exit0;
2101221167Sgnn	}
2102221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
2103221167Sgnn		vpath_handle = vxge_vpath_handle_get(vdev, i);
2104221167Sgnn		if (!vpath_handle)
2105221167Sgnn			continue;
2106221167Sgnn
2107221167Sgnn		status = vxge_hal_vpath_rts_rth_set(vpath_handle,
2108221167Sgnn		    RTH_ALG_JENKINS,
2109221167Sgnn		    &hash_types, vdev->config.rth_bkt_sz, TRUE);
2110221167Sgnn		if (status != VXGE_HAL_OK) {
2111221167Sgnn			device_printf(vdev->ndev,
2112221167Sgnn			    "rth configuration failed for vpath (%d)\n",
2113221167Sgnn			    vdev->vpaths[i].vp_id);
2114221167Sgnn			break;
2115221167Sgnn		}
2116221167Sgnn	}
2117221167Sgnn
2118221167Sgnn_exit0:
2119221167Sgnn	return (status);
2120221167Sgnn}
2121221167Sgnn
2122221167Sgnn/*
2123221167Sgnn * vxge_vpath_config
2124221167Sgnn * Sets HAL parameter values from kenv
2125221167Sgnn */
2126221167Sgnnvoid
2127221167Sgnnvxge_vpath_config(vxge_dev_t *vdev)
2128221167Sgnn{
2129221167Sgnn	int i;
2130221167Sgnn	u32 no_of_vpath = 0;
2131221167Sgnn	vxge_hal_vp_config_t *vp_config;
2132221167Sgnn	vxge_hal_device_config_t *device_config = vdev->device_config;
2133221167Sgnn
2134221167Sgnn	device_config->debug_level = VXGE_TRACE;
2135221167Sgnn	device_config->debug_mask = VXGE_COMPONENT_ALL;
2136221167Sgnn	device_config->device_poll_millis = VXGE_DEFAULT_DEVICE_POLL_MILLIS;
2137221167Sgnn
2138221167Sgnn	vdev->config.no_of_vpath =
2139221167Sgnn	    min(vdev->config.no_of_vpath, vdev->max_supported_vpath);
2140221167Sgnn
2141221167Sgnn	for (i = 0; i < VXGE_HAL_MAX_VIRTUAL_PATHS; i++) {
2142221167Sgnn		vp_config = &(device_config->vp_config[i]);
2143221167Sgnn		vp_config->fifo.enable = VXGE_HAL_FIFO_DISABLE;
2144221167Sgnn		vp_config->ring.enable = VXGE_HAL_RING_DISABLE;
2145221167Sgnn	}
2146221167Sgnn
2147221167Sgnn	for (i = 0; i < VXGE_HAL_MAX_VIRTUAL_PATHS; i++) {
2148221167Sgnn		if (no_of_vpath >= vdev->config.no_of_vpath)
2149221167Sgnn			break;
2150221167Sgnn
2151221167Sgnn		if (!bVAL1(vdev->config.hw_info.vpath_mask, i))
2152221167Sgnn			continue;
2153221167Sgnn
2154221167Sgnn		no_of_vpath++;
2155221167Sgnn		vp_config = &(device_config->vp_config[i]);
2156221167Sgnn		vp_config->mtu = VXGE_HAL_DEFAULT_MTU;
2157221167Sgnn		vp_config->ring.enable = VXGE_HAL_RING_ENABLE;
2158221167Sgnn		vp_config->ring.post_mode = VXGE_HAL_RING_POST_MODE_DOORBELL;
2159221167Sgnn		vp_config->ring.buffer_mode = VXGE_HAL_RING_RXD_BUFFER_MODE_1;
2160221167Sgnn		vp_config->ring.ring_length =
2161221167Sgnn		    vxge_ring_length_get(VXGE_HAL_RING_RXD_BUFFER_MODE_1);
2162221167Sgnn		vp_config->ring.scatter_mode = VXGE_HAL_RING_SCATTER_MODE_A;
2163221167Sgnn		vp_config->rpa_all_vid_en = VXGE_DEFAULT_ALL_VID_ENABLE;
2164221167Sgnn		vp_config->rpa_strip_vlan_tag = VXGE_DEFAULT_STRIP_VLAN_TAG;
2165221167Sgnn		vp_config->rpa_ucast_all_addr_en =
2166221167Sgnn		    VXGE_HAL_VPATH_RPA_UCAST_ALL_ADDR_DISABLE;
2167221167Sgnn
2168221167Sgnn		vp_config->rti.intr_enable = VXGE_HAL_TIM_INTR_ENABLE;
2169221167Sgnn		vp_config->rti.txfrm_cnt_en = VXGE_HAL_TXFRM_CNT_EN_ENABLE;
2170221167Sgnn		vp_config->rti.util_sel =
2171221167Sgnn		    VXGE_HAL_TIM_UTIL_SEL_LEGACY_RX_NET_UTIL;
2172221167Sgnn
2173221167Sgnn		vp_config->rti.uec_a = VXGE_DEFAULT_RTI_RX_UFC_A;
2174221167Sgnn		vp_config->rti.uec_b = VXGE_DEFAULT_RTI_RX_UFC_B;
2175221167Sgnn		vp_config->rti.uec_c = VXGE_DEFAULT_RTI_RX_UFC_C;
2176221167Sgnn		vp_config->rti.uec_d = VXGE_DEFAULT_RTI_RX_UFC_D;
2177221167Sgnn
2178221167Sgnn		vp_config->rti.urange_a = VXGE_DEFAULT_RTI_RX_URANGE_A;
2179221167Sgnn		vp_config->rti.urange_b = VXGE_DEFAULT_RTI_RX_URANGE_B;
2180221167Sgnn		vp_config->rti.urange_c = VXGE_DEFAULT_RTI_RX_URANGE_C;
2181221167Sgnn
2182221167Sgnn		vp_config->rti.timer_ac_en = VXGE_HAL_TIM_TIMER_AC_ENABLE;
2183221167Sgnn		vp_config->rti.timer_ci_en = VXGE_HAL_TIM_TIMER_CI_ENABLE;
2184221167Sgnn
2185221167Sgnn		vp_config->rti.btimer_val =
2186221167Sgnn		    (VXGE_DEFAULT_RTI_BTIMER_VAL * 1000) / 272;
2187221167Sgnn		vp_config->rti.rtimer_val =
2188221167Sgnn		    (VXGE_DEFAULT_RTI_RTIMER_VAL * 1000) / 272;
2189221167Sgnn		vp_config->rti.ltimer_val =
2190221167Sgnn		    (VXGE_DEFAULT_RTI_LTIMER_VAL * 1000) / 272;
2191221167Sgnn
2192221167Sgnn		if ((no_of_vpath > 1) && (VXGE_DEFAULT_CONFIG_MQ_ENABLE == 0))
2193221167Sgnn			continue;
2194221167Sgnn
2195221167Sgnn		vp_config->fifo.enable = VXGE_HAL_FIFO_ENABLE;
2196221167Sgnn		vp_config->fifo.max_aligned_frags =
2197221167Sgnn		    VXGE_DEFAULT_FIFO_ALIGNED_FRAGS;
2198221167Sgnn
2199221167Sgnn		vp_config->tti.intr_enable = VXGE_HAL_TIM_INTR_ENABLE;
2200221167Sgnn		vp_config->tti.txfrm_cnt_en = VXGE_HAL_TXFRM_CNT_EN_ENABLE;
2201221167Sgnn		vp_config->tti.util_sel =
2202221167Sgnn		    VXGE_HAL_TIM_UTIL_SEL_LEGACY_TX_NET_UTIL;
2203221167Sgnn
2204221167Sgnn		vp_config->tti.uec_a = VXGE_DEFAULT_TTI_TX_UFC_A;
2205221167Sgnn		vp_config->tti.uec_b = VXGE_DEFAULT_TTI_TX_UFC_B;
2206221167Sgnn		vp_config->tti.uec_c = VXGE_DEFAULT_TTI_TX_UFC_C;
2207221167Sgnn		vp_config->tti.uec_d = VXGE_DEFAULT_TTI_TX_UFC_D;
2208221167Sgnn
2209221167Sgnn		vp_config->tti.urange_a = VXGE_DEFAULT_TTI_TX_URANGE_A;
2210221167Sgnn		vp_config->tti.urange_b = VXGE_DEFAULT_TTI_TX_URANGE_B;
2211221167Sgnn		vp_config->tti.urange_c = VXGE_DEFAULT_TTI_TX_URANGE_C;
2212221167Sgnn
2213221167Sgnn		vp_config->tti.timer_ac_en = VXGE_HAL_TIM_TIMER_AC_ENABLE;
2214221167Sgnn		vp_config->tti.timer_ci_en = VXGE_HAL_TIM_TIMER_CI_ENABLE;
2215221167Sgnn
2216221167Sgnn		vp_config->tti.btimer_val =
2217221167Sgnn		    (VXGE_DEFAULT_TTI_BTIMER_VAL * 1000) / 272;
2218221167Sgnn		vp_config->tti.rtimer_val =
2219221167Sgnn		    (VXGE_DEFAULT_TTI_RTIMER_VAL * 1000) / 272;
2220221167Sgnn		vp_config->tti.ltimer_val =
2221221167Sgnn		    (VXGE_DEFAULT_TTI_LTIMER_VAL * 1000) / 272;
2222221167Sgnn	}
2223221167Sgnn
2224221167Sgnn	vdev->no_of_vpath = no_of_vpath;
2225221167Sgnn
2226221167Sgnn	if (vdev->no_of_vpath == 1)
2227221167Sgnn		vdev->config.tx_steering = 0;
2228221167Sgnn
2229221167Sgnn	if (vdev->config.rth_enable && (vdev->no_of_vpath > 1)) {
2230221167Sgnn		device_config->rth_en = VXGE_HAL_RTH_ENABLE;
2231221167Sgnn		device_config->rth_it_type = VXGE_HAL_RTH_IT_TYPE_MULTI_IT;
2232221167Sgnn	}
2233221167Sgnn
2234221167Sgnn	vdev->config.rth_enable = device_config->rth_en;
2235221167Sgnn}
2236221167Sgnn
2237221167Sgnn/*
2238221167Sgnn * vxge_vpath_cb_fn
2239221167Sgnn * Virtual path Callback function
2240221167Sgnn */
2241221167Sgnn/* ARGSUSED */
2242221167Sgnnstatic vxge_hal_status_e
2243221167Sgnnvxge_vpath_cb_fn(vxge_hal_client_h client_handle, vxge_hal_up_msg_h msgh,
2244221167Sgnn    vxge_hal_message_type_e msg_type, vxge_hal_obj_id_t obj_id,
2245221167Sgnn    vxge_hal_result_e result, vxge_hal_opaque_handle_t *opaque_handle)
2246221167Sgnn{
2247221167Sgnn	return (VXGE_HAL_OK);
2248221167Sgnn}
2249221167Sgnn
2250221167Sgnn/*
2251221167Sgnn * vxge_vpath_open
2252221167Sgnn */
2253221167Sgnnint
2254221167Sgnnvxge_vpath_open(vxge_dev_t *vdev)
2255221167Sgnn{
2256221167Sgnn	int i, err = EINVAL;
2257221167Sgnn	u64 func_id;
2258221167Sgnn
2259221167Sgnn	vxge_vpath_t *vpath;
2260221167Sgnn	vxge_hal_vpath_attr_t vpath_attr;
2261221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
2262221167Sgnn	struct lro_ctrl *lro = NULL;
2263221167Sgnn
2264221167Sgnn	bzero(&vpath_attr, sizeof(vxge_hal_vpath_attr_t));
2265221167Sgnn
2266221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
2267221167Sgnn
2268221167Sgnn		vpath = &(vdev->vpaths[i]);
2269221167Sgnn		lro = &vpath->lro;
2270221167Sgnn
2271221167Sgnn		/* Vpath vpath_attr: FIFO */
2272221167Sgnn		vpath_attr.vp_id = vpath->vp_id;
2273221167Sgnn		vpath_attr.fifo_attr.callback = vxge_tx_compl;
2274221167Sgnn		vpath_attr.fifo_attr.txdl_init = vxge_tx_replenish;
2275221167Sgnn		vpath_attr.fifo_attr.txdl_term = vxge_tx_term;
2276221167Sgnn		vpath_attr.fifo_attr.userdata = vpath;
2277221167Sgnn		vpath_attr.fifo_attr.per_txdl_space = sizeof(vxge_txdl_priv_t);
2278221167Sgnn
2279221167Sgnn		/* Vpath vpath_attr: Ring */
2280221167Sgnn		vpath_attr.ring_attr.callback = vxge_rx_compl;
2281221167Sgnn		vpath_attr.ring_attr.rxd_init = vxge_rx_replenish;
2282221167Sgnn		vpath_attr.ring_attr.rxd_term = vxge_rx_term;
2283221167Sgnn		vpath_attr.ring_attr.userdata = vpath;
2284221167Sgnn		vpath_attr.ring_attr.per_rxd_space = sizeof(vxge_rxd_priv_t);
2285221167Sgnn
2286221167Sgnn		err = vxge_dma_tags_create(vpath);
2287221167Sgnn		if (err != 0) {
2288221167Sgnn			device_printf(vdev->ndev,
2289221167Sgnn			    "failed to create dma tags\n");
2290221167Sgnn			break;
2291221167Sgnn		}
2292221167Sgnn#if __FreeBSD_version >= 800000
2293221167Sgnn		vpath->br = buf_ring_alloc(VXGE_DEFAULT_BR_SIZE, M_DEVBUF,
2294221167Sgnn		    M_WAITOK, &vpath->mtx_tx);
2295221167Sgnn		if (vpath->br == NULL) {
2296221167Sgnn			err = ENOMEM;
2297221167Sgnn			break;
2298221167Sgnn		}
2299221167Sgnn#endif
2300221167Sgnn		status = vxge_hal_vpath_open(vdev->devh, &vpath_attr,
2301221167Sgnn		    (vxge_hal_vpath_callback_f) vxge_vpath_cb_fn,
2302221167Sgnn		    NULL, &vpath->handle);
2303221167Sgnn		if (status != VXGE_HAL_OK) {
2304221167Sgnn			device_printf(vdev->ndev,
2305221167Sgnn			    "failed to open vpath (%d)\n", vpath->vp_id);
2306221167Sgnn			err = EPERM;
2307221167Sgnn			break;
2308221167Sgnn		}
2309221167Sgnn		vpath->is_open = TRUE;
2310221167Sgnn		vdev->vpath_handles[i] = vpath->handle;
2311221167Sgnn
2312221167Sgnn		vpath->tx_ticks = ticks;
2313221167Sgnn		vpath->rx_ticks = ticks;
2314221167Sgnn
2315221167Sgnn		vpath->tti_rtimer_val = VXGE_DEFAULT_TTI_RTIMER_VAL;
2316221167Sgnn		vpath->tti_rtimer_val = VXGE_DEFAULT_TTI_RTIMER_VAL;
2317221167Sgnn
2318221167Sgnn		vpath->tx_intr_coalesce = vdev->config.intr_coalesce;
2319221167Sgnn		vpath->rx_intr_coalesce = vdev->config.intr_coalesce;
2320221167Sgnn
2321221167Sgnn		func_id = vdev->config.hw_info.func_id;
2322221167Sgnn
2323221167Sgnn		if (vdev->config.low_latency &&
2324221167Sgnn		    (vdev->config.bw_info[func_id].priority ==
2325221167Sgnn			VXGE_DEFAULT_VPATH_PRIORITY_HIGH)) {
2326221167Sgnn			vpath->tx_intr_coalesce = 0;
2327221167Sgnn		}
2328221167Sgnn
2329221167Sgnn		if (vdev->ifp->if_capenable & IFCAP_LRO) {
2330221167Sgnn			err = tcp_lro_init(lro);
2331221167Sgnn			if (err != 0) {
2332221167Sgnn				device_printf(vdev->ndev,
2333221167Sgnn				    "LRO Initialization failed!\n");
2334221167Sgnn				break;
2335221167Sgnn			}
2336221167Sgnn			vpath->lro_enable = TRUE;
2337221167Sgnn			lro->ifp = vdev->ifp;
2338221167Sgnn		}
2339221167Sgnn	}
2340221167Sgnn
2341221167Sgnn	return (err);
2342221167Sgnn}
2343221167Sgnn
2344221167Sgnnvoid
2345221167Sgnnvxge_tso_config(vxge_dev_t *vdev)
2346221167Sgnn{
2347221167Sgnn	u32 func_id, priority;
2348221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
2349221167Sgnn
2350221167Sgnn	vdev->ifp->if_capabilities |= IFCAP_TSO4;
2351221167Sgnn
2352221167Sgnn	status = vxge_bw_priority_get(vdev, NULL);
2353221167Sgnn	if (status == VXGE_HAL_OK) {
2354221167Sgnn
2355221167Sgnn		func_id = vdev->config.hw_info.func_id;
2356221167Sgnn		priority = vdev->config.bw_info[func_id].priority;
2357221167Sgnn
2358221167Sgnn		if (priority != VXGE_DEFAULT_VPATH_PRIORITY_HIGH)
2359221167Sgnn			vdev->ifp->if_capabilities &= ~IFCAP_TSO4;
2360221167Sgnn	}
2361221167Sgnn
2362221167Sgnn#if __FreeBSD_version >= 800000
2363221167Sgnn	if (vdev->ifp->if_capabilities & IFCAP_TSO4)
2364221167Sgnn		vdev->ifp->if_capabilities |= IFCAP_VLAN_HWTSO;
2365221167Sgnn#endif
2366221167Sgnn
2367221167Sgnn}
2368221167Sgnn
2369221167Sgnnvxge_hal_status_e
2370221167Sgnnvxge_bw_priority_get(vxge_dev_t *vdev, vxge_bw_info_t *bw_info)
2371221167Sgnn{
2372221167Sgnn	u32 priority, bandwidth;
2373221167Sgnn	u32 vpath_count;
2374221167Sgnn
2375221167Sgnn	u64 func_id, func_mode, vpath_list[VXGE_HAL_MAX_VIRTUAL_PATHS];
2376221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
2377221167Sgnn
2378221167Sgnn	func_id = vdev->config.hw_info.func_id;
2379221167Sgnn	if (bw_info) {
2380221167Sgnn		func_id = bw_info->func_id;
2381221167Sgnn		func_mode = vdev->config.hw_info.function_mode;
2382221167Sgnn		if ((is_single_func(func_mode)) && (func_id > 0))
2383221167Sgnn			return (VXGE_HAL_FAIL);
2384221167Sgnn	}
2385221167Sgnn
2386221167Sgnn	if (vdev->hw_fw_version >= VXGE_FW_VERSION(1, 8, 0)) {
2387221167Sgnn
2388221167Sgnn		status = vxge_hal_vf_rx_bw_get(vdev->devh,
2389221167Sgnn		    func_id, &bandwidth, &priority);
2390221167Sgnn
2391221167Sgnn	} else {
2392221167Sgnn
2393221167Sgnn		status = vxge_hal_get_vpath_list(vdev->devh,
2394221167Sgnn		    func_id, vpath_list, &vpath_count);
2395221167Sgnn
2396221167Sgnn		if (status == VXGE_HAL_OK) {
2397221167Sgnn			status = vxge_hal_bw_priority_get(vdev->devh,
2398221167Sgnn			    vpath_list[0], &bandwidth, &priority);
2399221167Sgnn		}
2400221167Sgnn	}
2401221167Sgnn
2402221167Sgnn	if (status == VXGE_HAL_OK) {
2403221167Sgnn		if (bw_info) {
2404221167Sgnn			bw_info->priority = priority;
2405221167Sgnn			bw_info->bandwidth = bandwidth;
2406221167Sgnn		} else {
2407221167Sgnn			vdev->config.bw_info[func_id].priority = priority;
2408221167Sgnn			vdev->config.bw_info[func_id].bandwidth = bandwidth;
2409221167Sgnn		}
2410221167Sgnn	}
2411221167Sgnn
2412221167Sgnn	return (status);
2413221167Sgnn}
2414221167Sgnn
2415221167Sgnn/*
2416221167Sgnn * close vpaths
2417221167Sgnn */
2418221167Sgnnvoid
2419221167Sgnnvxge_vpath_close(vxge_dev_t *vdev)
2420221167Sgnn{
2421221167Sgnn	int i;
2422221167Sgnn	vxge_vpath_t *vpath;
2423221167Sgnn
2424221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
2425221167Sgnn
2426221167Sgnn		vpath = &(vdev->vpaths[i]);
2427221167Sgnn		if (vpath->handle)
2428221167Sgnn			vxge_hal_vpath_close(vpath->handle);
2429221167Sgnn
2430221167Sgnn#if __FreeBSD_version >= 800000
2431221167Sgnn		if (vpath->br != NULL)
2432221167Sgnn			buf_ring_free(vpath->br, M_DEVBUF);
2433221167Sgnn#endif
2434221167Sgnn		/* Free LRO memory */
2435221167Sgnn		if (vpath->lro_enable)
2436221167Sgnn			tcp_lro_free(&vpath->lro);
2437221167Sgnn
2438221167Sgnn		if (vpath->dma_tag_rx) {
2439221167Sgnn			bus_dmamap_destroy(vpath->dma_tag_rx,
2440221167Sgnn			    vpath->extra_dma_map);
2441221167Sgnn			bus_dma_tag_destroy(vpath->dma_tag_rx);
2442221167Sgnn		}
2443221167Sgnn
2444221167Sgnn		if (vpath->dma_tag_tx)
2445221167Sgnn			bus_dma_tag_destroy(vpath->dma_tag_tx);
2446221167Sgnn
2447221167Sgnn		vpath->handle = NULL;
2448221167Sgnn		vpath->is_open = FALSE;
2449221167Sgnn	}
2450221167Sgnn}
2451221167Sgnn
2452221167Sgnn/*
2453221167Sgnn * reset vpaths
2454221167Sgnn */
2455221167Sgnnvoid
2456221167Sgnnvxge_vpath_reset(vxge_dev_t *vdev)
2457221167Sgnn{
2458221167Sgnn	int i;
2459221167Sgnn	vxge_hal_vpath_h vpath_handle;
2460221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
2461221167Sgnn
2462221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
2463221167Sgnn		vpath_handle = vxge_vpath_handle_get(vdev, i);
2464221167Sgnn		if (!vpath_handle)
2465221167Sgnn			continue;
2466221167Sgnn
2467221167Sgnn		status = vxge_hal_vpath_reset(vpath_handle);
2468221167Sgnn		if (status != VXGE_HAL_OK)
2469221167Sgnn			device_printf(vdev->ndev,
2470221167Sgnn			    "failed to reset vpath :%d\n", i);
2471221167Sgnn	}
2472221167Sgnn}
2473221167Sgnn
2474221167Sgnnstatic inline int
2475221167Sgnnvxge_vpath_get(vxge_dev_t *vdev, mbuf_t mhead)
2476221167Sgnn{
2477221167Sgnn	struct tcphdr *th = NULL;
2478221167Sgnn	struct udphdr *uh = NULL;
2479221167Sgnn	struct ip *ip = NULL;
2480221167Sgnn	struct ip6_hdr *ip6 = NULL;
2481221167Sgnn	struct ether_vlan_header *eth = NULL;
2482221167Sgnn	void *ulp = NULL;
2483221167Sgnn
2484221167Sgnn	int ehdrlen, iphlen = 0;
2485221167Sgnn	u8 ipproto = 0;
2486221167Sgnn	u16 etype, src_port, dst_port;
2487221167Sgnn	u16 queue_len, counter = 0;
2488221167Sgnn
2489221167Sgnn	src_port = dst_port = 0;
2490221167Sgnn	queue_len = vdev->no_of_vpath;
2491221167Sgnn
2492221167Sgnn	eth = mtod(mhead, struct ether_vlan_header *);
2493221167Sgnn	if (eth->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
2494221167Sgnn		etype = ntohs(eth->evl_proto);
2495221167Sgnn		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
2496221167Sgnn	} else {
2497221167Sgnn		etype = ntohs(eth->evl_encap_proto);
2498221167Sgnn		ehdrlen = ETHER_HDR_LEN;
2499221167Sgnn	}
2500221167Sgnn
2501221167Sgnn	switch (etype) {
2502221167Sgnn	case ETHERTYPE_IP:
2503221167Sgnn		ip = (struct ip *) (mhead->m_data + ehdrlen);
2504221167Sgnn		iphlen = ip->ip_hl << 2;
2505221167Sgnn		ipproto = ip->ip_p;
2506221167Sgnn		th = (struct tcphdr *) ((caddr_t)ip + iphlen);
2507221167Sgnn		uh = (struct udphdr *) ((caddr_t)ip + iphlen);
2508221167Sgnn		break;
2509221167Sgnn
2510221167Sgnn	case ETHERTYPE_IPV6:
2511221167Sgnn		ip6 = (struct ip6_hdr *) (mhead->m_data + ehdrlen);
2512221167Sgnn		iphlen = sizeof(struct ip6_hdr);
2513221167Sgnn		ipproto = ip6->ip6_nxt;
2514221167Sgnn
2515221167Sgnn		ulp = mtod(mhead, char *) + iphlen;
2516221167Sgnn		th = ((struct tcphdr *) (ulp));
2517221167Sgnn		uh = ((struct udphdr *) (ulp));
2518221167Sgnn		break;
2519221167Sgnn
2520221167Sgnn	default:
2521221167Sgnn		break;
2522221167Sgnn	}
2523221167Sgnn
2524221167Sgnn	switch (ipproto) {
2525221167Sgnn	case IPPROTO_TCP:
2526221167Sgnn		src_port = th->th_sport;
2527221167Sgnn		dst_port = th->th_dport;
2528221167Sgnn		break;
2529221167Sgnn
2530221167Sgnn	case IPPROTO_UDP:
2531221167Sgnn		src_port = uh->uh_sport;
2532221167Sgnn		dst_port = uh->uh_dport;
2533221167Sgnn		break;
2534221167Sgnn
2535221167Sgnn	default:
2536221167Sgnn		break;
2537221167Sgnn	}
2538221167Sgnn
2539221167Sgnn	counter = (ntohs(src_port) + ntohs(dst_port)) &
2540221167Sgnn	    vpath_selector[queue_len - 1];
2541221167Sgnn
2542221167Sgnn	if (counter >= queue_len)
2543221167Sgnn		counter = queue_len - 1;
2544221167Sgnn
2545221167Sgnn	return (counter);
2546221167Sgnn}
2547221167Sgnn
2548221167Sgnnstatic inline vxge_hal_vpath_h
2549221167Sgnnvxge_vpath_handle_get(vxge_dev_t *vdev, int i)
2550221167Sgnn{
2551221167Sgnn	return (vdev->vpaths[i].is_open ? vdev->vpaths[i].handle : NULL);
2552221167Sgnn}
2553221167Sgnn
2554221167Sgnnint
2555221167Sgnnvxge_firmware_verify(vxge_dev_t *vdev)
2556221167Sgnn{
2557221167Sgnn	int err = 0;
2558221167Sgnn	u64 active_config;
2559221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2560221167Sgnn
2561221167Sgnn	if (vdev->fw_upgrade) {
2562221167Sgnn		status = vxge_firmware_upgrade(vdev);
2563221167Sgnn		if (status == VXGE_HAL_OK) {
2564221167Sgnn			err = ENXIO;
2565221167Sgnn			goto _exit0;
2566221167Sgnn		}
2567221167Sgnn	}
2568221167Sgnn
2569221167Sgnn	if ((vdev->config.function_mode != VXGE_DEFAULT_CONFIG_VALUE) &&
2570221167Sgnn	    (vdev->config.hw_info.function_mode !=
2571221167Sgnn	    (u64) vdev->config.function_mode)) {
2572221167Sgnn
2573221167Sgnn		status = vxge_func_mode_set(vdev);
2574221167Sgnn		if (status == VXGE_HAL_OK)
2575221167Sgnn			err = ENXIO;
2576221167Sgnn	}
2577221167Sgnn
2578221167Sgnn	/* l2_switch configuration */
2579221167Sgnn	active_config = VXGE_DEFAULT_CONFIG_VALUE;
2580221167Sgnn	status = vxge_hal_get_active_config(vdev->devh,
2581221167Sgnn	    VXGE_HAL_XMAC_NWIF_ActConfig_L2SwitchEnabled,
2582221167Sgnn	    &active_config);
2583221167Sgnn
2584221167Sgnn	if (status == VXGE_HAL_OK) {
2585221167Sgnn		vdev->l2_switch = active_config;
2586221167Sgnn		if (vdev->config.l2_switch != VXGE_DEFAULT_CONFIG_VALUE) {
2587221167Sgnn			if (vdev->config.l2_switch != active_config) {
2588221167Sgnn				status = vxge_l2switch_mode_set(vdev);
2589221167Sgnn				if (status == VXGE_HAL_OK)
2590221167Sgnn					err = ENXIO;
2591221167Sgnn			}
2592221167Sgnn		}
2593221167Sgnn	}
2594221167Sgnn
2595221167Sgnn	if (vdev->config.hw_info.ports == VXGE_DUAL_PORT_MODE) {
2596221167Sgnn		if (vxge_port_mode_update(vdev) == ENXIO)
2597221167Sgnn			err = ENXIO;
2598221167Sgnn	}
2599221167Sgnn
2600221167Sgnn_exit0:
2601221167Sgnn	if (err == ENXIO)
2602221167Sgnn		device_printf(vdev->ndev, "PLEASE POWER CYCLE THE SYSTEM\n");
2603221167Sgnn
2604221167Sgnn	return (err);
2605221167Sgnn}
2606221167Sgnn
2607221167Sgnnvxge_hal_status_e
2608221167Sgnnvxge_firmware_upgrade(vxge_dev_t *vdev)
2609221167Sgnn{
2610221167Sgnn	u8 *fw_buffer;
2611221167Sgnn	u32 fw_size;
2612221167Sgnn	vxge_hal_device_hw_info_t *hw_info;
2613221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
2614221167Sgnn
2615221167Sgnn	hw_info = &vdev->config.hw_info;
2616221167Sgnn
2617221167Sgnn	fw_size = sizeof(VXGE_FW_ARRAY_NAME);
2618221167Sgnn	fw_buffer = (u8 *) VXGE_FW_ARRAY_NAME;
2619221167Sgnn
2620221167Sgnn	device_printf(vdev->ndev, "Current firmware version : %s (%s)\n",
2621221167Sgnn	    hw_info->fw_version.version, hw_info->fw_date.date);
2622221167Sgnn
2623221167Sgnn	device_printf(vdev->ndev, "Upgrading firmware to %d.%d.%d\n",
2624221167Sgnn	    VXGE_MIN_FW_MAJOR_VERSION, VXGE_MIN_FW_MINOR_VERSION,
2625221167Sgnn	    VXGE_MIN_FW_BUILD_NUMBER);
2626221167Sgnn
2627221167Sgnn	/* Call HAL API to upgrade firmware */
2628221167Sgnn	status = vxge_hal_mrpcim_fw_upgrade(vdev->pdev,
2629221167Sgnn	    (pci_reg_h) vdev->pdev->reg_map[0],
2630221167Sgnn	    (u8 *) vdev->pdev->bar_info[0],
2631221167Sgnn	    fw_buffer, fw_size);
2632221167Sgnn
2633221167Sgnn	device_printf(vdev->ndev, "firmware upgrade %s\n",
2634221167Sgnn	    (status == VXGE_HAL_OK) ? "successful" : "failed");
2635221167Sgnn
2636221167Sgnn	return (status);
2637221167Sgnn}
2638221167Sgnn
2639221167Sgnnvxge_hal_status_e
2640221167Sgnnvxge_func_mode_set(vxge_dev_t *vdev)
2641221167Sgnn{
2642221167Sgnn	u64 active_config;
2643221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2644221167Sgnn
2645221167Sgnn	status = vxge_hal_mrpcim_pcie_func_mode_set(vdev->devh,
2646221167Sgnn	    vdev->config.function_mode);
2647221167Sgnn	device_printf(vdev->ndev,
2648221167Sgnn	    "function mode change %s\n",
2649221167Sgnn	    (status == VXGE_HAL_OK) ? "successful" : "failed");
2650221167Sgnn
2651221167Sgnn	if (status == VXGE_HAL_OK) {
2652221167Sgnn		vxge_hal_set_fw_api(vdev->devh, 0ULL,
2653221167Sgnn		    VXGE_HAL_API_FUNC_MODE_COMMIT,
2654221167Sgnn		    0, 0ULL, 0ULL);
2655221167Sgnn
2656221167Sgnn		vxge_hal_get_active_config(vdev->devh,
2657221167Sgnn		    VXGE_HAL_XMAC_NWIF_ActConfig_NWPortMode,
2658221167Sgnn		    &active_config);
2659221167Sgnn
2660221167Sgnn		/*
2661221167Sgnn		 * If in MF + DP mode
2662221167Sgnn		 * if user changes to SF, change port_mode to single port mode
2663221167Sgnn		 */
2664221167Sgnn		if (((is_multi_func(vdev->config.hw_info.function_mode)) &&
2665221167Sgnn		    is_single_func(vdev->config.function_mode)) &&
2666221167Sgnn		    (active_config == VXGE_HAL_DP_NP_MODE_DUAL_PORT)) {
2667221167Sgnn			vdev->config.port_mode =
2668221167Sgnn			    VXGE_HAL_DP_NP_MODE_SINGLE_PORT;
2669221167Sgnn
2670221167Sgnn			status = vxge_port_mode_set(vdev);
2671221167Sgnn		}
2672221167Sgnn	}
2673221167Sgnn	return (status);
2674221167Sgnn}
2675221167Sgnn
2676221167Sgnnvxge_hal_status_e
2677221167Sgnnvxge_port_mode_set(vxge_dev_t *vdev)
2678221167Sgnn{
2679221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2680221167Sgnn
2681221167Sgnn	status = vxge_hal_set_port_mode(vdev->devh, vdev->config.port_mode);
2682221167Sgnn	device_printf(vdev->ndev,
2683221167Sgnn	    "port mode change %s\n",
2684221167Sgnn	    (status == VXGE_HAL_OK) ? "successful" : "failed");
2685221167Sgnn
2686221167Sgnn	if (status == VXGE_HAL_OK) {
2687221167Sgnn		vxge_hal_set_fw_api(vdev->devh, 0ULL,
2688221167Sgnn		    VXGE_HAL_API_FUNC_MODE_COMMIT,
2689221167Sgnn		    0, 0ULL, 0ULL);
2690221167Sgnn
2691221167Sgnn		/* Configure vpath_mapping for active-active mode only */
2692221167Sgnn		if (vdev->config.port_mode == VXGE_HAL_DP_NP_MODE_DUAL_PORT) {
2693221167Sgnn
2694221167Sgnn			status = vxge_hal_config_vpath_map(vdev->devh,
2695221167Sgnn			    VXGE_DUAL_PORT_MAP);
2696221167Sgnn
2697221167Sgnn			device_printf(vdev->ndev, "dual port map change %s\n",
2698221167Sgnn			    (status == VXGE_HAL_OK) ? "successful" : "failed");
2699221167Sgnn		}
2700221167Sgnn	}
2701221167Sgnn	return (status);
2702221167Sgnn}
2703221167Sgnn
2704221167Sgnnint
2705221167Sgnnvxge_port_mode_update(vxge_dev_t *vdev)
2706221167Sgnn{
2707221167Sgnn	int err = 0;
2708221167Sgnn	u64 active_config;
2709221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2710221167Sgnn
2711221167Sgnn	if ((vdev->config.port_mode == VXGE_HAL_DP_NP_MODE_DUAL_PORT) &&
2712221167Sgnn	    is_single_func(vdev->config.hw_info.function_mode)) {
2713221167Sgnn
2714221167Sgnn		device_printf(vdev->ndev,
2715221167Sgnn		    "Adapter in SF mode, dual port mode is not allowed\n");
2716221167Sgnn		err = EPERM;
2717221167Sgnn		goto _exit0;
2718221167Sgnn	}
2719221167Sgnn
2720221167Sgnn	active_config = VXGE_DEFAULT_CONFIG_VALUE;
2721221167Sgnn	status = vxge_hal_get_active_config(vdev->devh,
2722221167Sgnn	    VXGE_HAL_XMAC_NWIF_ActConfig_NWPortMode,
2723221167Sgnn	    &active_config);
2724221167Sgnn	if (status != VXGE_HAL_OK) {
2725221167Sgnn		err = EINVAL;
2726221167Sgnn		goto _exit0;
2727221167Sgnn	}
2728221167Sgnn
2729221167Sgnn	vdev->port_mode = active_config;
2730221167Sgnn	if (vdev->config.port_mode != VXGE_DEFAULT_CONFIG_VALUE) {
2731221167Sgnn		if (vdev->config.port_mode != vdev->port_mode) {
2732221167Sgnn			status = vxge_port_mode_set(vdev);
2733221167Sgnn			if (status != VXGE_HAL_OK) {
2734221167Sgnn				err = EINVAL;
2735221167Sgnn				goto _exit0;
2736221167Sgnn			}
2737221167Sgnn			err = ENXIO;
2738221167Sgnn			vdev->port_mode  = vdev->config.port_mode;
2739221167Sgnn		}
2740221167Sgnn	}
2741221167Sgnn
2742221167Sgnn	active_config = VXGE_DEFAULT_CONFIG_VALUE;
2743221167Sgnn	status = vxge_hal_get_active_config(vdev->devh,
2744221167Sgnn	    VXGE_HAL_XMAC_NWIF_ActConfig_BehaviourOnFail,
2745221167Sgnn	    &active_config);
2746221167Sgnn	if (status != VXGE_HAL_OK) {
2747221167Sgnn		err = EINVAL;
2748221167Sgnn		goto _exit0;
2749221167Sgnn	}
2750221167Sgnn
2751221167Sgnn	vdev->port_failure = active_config;
2752221167Sgnn
2753221167Sgnn	/*
2754221167Sgnn	 * active/active mode : set to NoMove
2755221167Sgnn	 * active/passive mode: set to Failover-Failback
2756221167Sgnn	 */
2757221167Sgnn	if (vdev->port_mode == VXGE_HAL_DP_NP_MODE_DUAL_PORT)
2758221167Sgnn		vdev->config.port_failure =
2759221167Sgnn		    VXGE_HAL_XMAC_NWIF_OnFailure_NoMove;
2760221167Sgnn
2761221167Sgnn	else if (vdev->port_mode == VXGE_HAL_DP_NP_MODE_ACTIVE_PASSIVE)
2762221167Sgnn		vdev->config.port_failure =
2763221167Sgnn		    VXGE_HAL_XMAC_NWIF_OnFailure_OtherPortBackOnRestore;
2764221167Sgnn
2765221167Sgnn	if ((vdev->port_mode != VXGE_HAL_DP_NP_MODE_SINGLE_PORT) &&
2766221167Sgnn	    (vdev->config.port_failure != vdev->port_failure)) {
2767221167Sgnn		status = vxge_port_behavior_on_failure_set(vdev);
2768221167Sgnn		if (status == VXGE_HAL_OK)
2769221167Sgnn			err = ENXIO;
2770221167Sgnn	}
2771221167Sgnn
2772221167Sgnn_exit0:
2773221167Sgnn	return (err);
2774221167Sgnn}
2775221167Sgnn
2776221167Sgnnvxge_hal_status_e
2777221167Sgnnvxge_port_mode_get(vxge_dev_t *vdev, vxge_port_info_t *port_info)
2778221167Sgnn{
2779221167Sgnn	int err = 0;
2780221167Sgnn	u64 active_config;
2781221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2782221167Sgnn
2783221167Sgnn	active_config = VXGE_DEFAULT_CONFIG_VALUE;
2784221167Sgnn	status = vxge_hal_get_active_config(vdev->devh,
2785221167Sgnn	    VXGE_HAL_XMAC_NWIF_ActConfig_NWPortMode,
2786221167Sgnn	    &active_config);
2787221167Sgnn
2788221167Sgnn	if (status != VXGE_HAL_OK) {
2789221167Sgnn		err = ENXIO;
2790221167Sgnn		goto _exit0;
2791221167Sgnn	}
2792221167Sgnn
2793221167Sgnn	port_info->port_mode = active_config;
2794221167Sgnn
2795221167Sgnn	active_config = VXGE_DEFAULT_CONFIG_VALUE;
2796221167Sgnn	status = vxge_hal_get_active_config(vdev->devh,
2797221167Sgnn	    VXGE_HAL_XMAC_NWIF_ActConfig_BehaviourOnFail,
2798221167Sgnn	    &active_config);
2799221167Sgnn	if (status != VXGE_HAL_OK) {
2800221167Sgnn		err = ENXIO;
2801221167Sgnn		goto _exit0;
2802221167Sgnn	}
2803221167Sgnn
2804221167Sgnn	port_info->port_failure = active_config;
2805221167Sgnn
2806221167Sgnn_exit0:
2807221167Sgnn	return (err);
2808221167Sgnn}
2809221167Sgnn
2810221167Sgnnvxge_hal_status_e
2811221167Sgnnvxge_port_behavior_on_failure_set(vxge_dev_t *vdev)
2812221167Sgnn{
2813221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2814221167Sgnn
2815221167Sgnn	status = vxge_hal_set_behavior_on_failure(vdev->devh,
2816221167Sgnn	    vdev->config.port_failure);
2817221167Sgnn
2818221167Sgnn	device_printf(vdev->ndev,
2819221167Sgnn	    "port behaviour on failure change %s\n",
2820221167Sgnn	    (status == VXGE_HAL_OK) ? "successful" : "failed");
2821221167Sgnn
2822221167Sgnn	if (status == VXGE_HAL_OK)
2823221167Sgnn		vxge_hal_set_fw_api(vdev->devh, 0ULL,
2824221167Sgnn		    VXGE_HAL_API_FUNC_MODE_COMMIT,
2825221167Sgnn		    0, 0ULL, 0ULL);
2826221167Sgnn
2827221167Sgnn	return (status);
2828221167Sgnn}
2829221167Sgnn
2830221167Sgnnvoid
2831221167Sgnnvxge_active_port_update(vxge_dev_t *vdev)
2832221167Sgnn{
2833221167Sgnn	u64 active_config;
2834221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2835221167Sgnn
2836221167Sgnn	active_config = VXGE_DEFAULT_CONFIG_VALUE;
2837221167Sgnn	status = vxge_hal_get_active_config(vdev->devh,
2838221167Sgnn	    VXGE_HAL_XMAC_NWIF_ActConfig_ActivePort,
2839221167Sgnn	    &active_config);
2840221167Sgnn
2841221167Sgnn	if (status == VXGE_HAL_OK)
2842221167Sgnn		vdev->active_port = active_config;
2843221167Sgnn}
2844221167Sgnn
2845221167Sgnnvxge_hal_status_e
2846221167Sgnnvxge_l2switch_mode_set(vxge_dev_t *vdev)
2847221167Sgnn{
2848221167Sgnn	vxge_hal_status_e status = VXGE_HAL_FAIL;
2849221167Sgnn
2850221167Sgnn	status = vxge_hal_set_l2switch_mode(vdev->devh,
2851221167Sgnn	    vdev->config.l2_switch);
2852221167Sgnn
2853221167Sgnn	device_printf(vdev->ndev, "L2 switch %s\n",
2854221167Sgnn	    (status == VXGE_HAL_OK) ?
2855221167Sgnn	    (vdev->config.l2_switch) ? "enable" : "disable" :
2856221167Sgnn	    "change failed");
2857221167Sgnn
2858221167Sgnn	if (status == VXGE_HAL_OK)
2859221167Sgnn		vxge_hal_set_fw_api(vdev->devh, 0ULL,
2860221167Sgnn		    VXGE_HAL_API_FUNC_MODE_COMMIT,
2861221167Sgnn		    0, 0ULL, 0ULL);
2862221167Sgnn
2863221167Sgnn	return (status);
2864221167Sgnn}
2865221167Sgnn
2866221167Sgnn/*
2867221167Sgnn * vxge_promisc_set
2868221167Sgnn * Enable Promiscuous Mode
2869221167Sgnn */
2870221167Sgnnvoid
2871221167Sgnnvxge_promisc_set(vxge_dev_t *vdev)
2872221167Sgnn{
2873221167Sgnn	int i;
2874221167Sgnn	ifnet_t ifp;
2875221167Sgnn	vxge_hal_vpath_h vpath_handle;
2876221167Sgnn
2877221167Sgnn	if (!vdev->is_initialized)
2878221167Sgnn		return;
2879221167Sgnn
2880221167Sgnn	ifp = vdev->ifp;
2881221167Sgnn
2882221167Sgnn	if ((ifp->if_flags & IFF_ALLMULTI) && (!vdev->all_multi_flag)) {
2883221167Sgnn		for (i = 0; i < vdev->no_of_vpath; i++) {
2884221167Sgnn			vpath_handle = vxge_vpath_handle_get(vdev, i);
2885221167Sgnn			if (!vpath_handle)
2886221167Sgnn				continue;
2887221167Sgnn
2888221167Sgnn			vxge_hal_vpath_mcast_enable(vpath_handle);
2889221167Sgnn			vdev->all_multi_flag = 1;
2890221167Sgnn		}
2891221167Sgnn
2892221167Sgnn	} else if (!(ifp->if_flags & IFF_ALLMULTI) && (vdev->all_multi_flag)) {
2893221167Sgnn		for (i = 0; i < vdev->no_of_vpath; i++) {
2894221167Sgnn			vpath_handle = vxge_vpath_handle_get(vdev, i);
2895221167Sgnn			if (!vpath_handle)
2896221167Sgnn				continue;
2897221167Sgnn
2898221167Sgnn			vxge_hal_vpath_mcast_disable(vpath_handle);
2899221167Sgnn			vdev->all_multi_flag = 0;
2900221167Sgnn		}
2901221167Sgnn	}
2902221167Sgnn	for (i = 0; i < vdev->no_of_vpath; i++) {
2903221167Sgnn		vpath_handle = vxge_vpath_handle_get(vdev, i);
2904221167Sgnn		if (!vpath_handle)
2905221167Sgnn			continue;
2906221167Sgnn
2907221167Sgnn		if (ifp->if_flags & IFF_PROMISC)
2908221167Sgnn			vxge_hal_vpath_promisc_enable(vpath_handle);
2909221167Sgnn		else
2910221167Sgnn			vxge_hal_vpath_promisc_disable(vpath_handle);
2911221167Sgnn	}
2912221167Sgnn}
2913221167Sgnn
2914221167Sgnn/*
2915221167Sgnn * vxge_change_mtu
2916221167Sgnn * Change interface MTU to a requested valid size
2917221167Sgnn */
2918221167Sgnnint
2919221167Sgnnvxge_change_mtu(vxge_dev_t *vdev, unsigned long new_mtu)
2920221167Sgnn{
2921221167Sgnn	int err = EINVAL;
2922221167Sgnn
2923221167Sgnn	if ((new_mtu < VXGE_HAL_MIN_MTU) || (new_mtu > VXGE_HAL_MAX_MTU))
2924221167Sgnn		goto _exit0;
2925221167Sgnn
2926221167Sgnn	(vdev->ifp)->if_mtu = new_mtu;
2927221167Sgnn	device_printf(vdev->ndev, "MTU changed to %ld\n", (vdev->ifp)->if_mtu);
2928221167Sgnn
2929221167Sgnn	if (vdev->is_initialized) {
2930221167Sgnn		if_down(vdev->ifp);
2931221167Sgnn		vxge_reset(vdev);
2932221167Sgnn		if_up(vdev->ifp);
2933221167Sgnn	}
2934221167Sgnn	err = 0;
2935221167Sgnn
2936221167Sgnn_exit0:
2937221167Sgnn	return (err);
2938221167Sgnn}
2939221167Sgnn
2940221167Sgnn/*
2941221167Sgnn * Creates DMA tags for both Tx and Rx
2942221167Sgnn */
2943221167Sgnnint
2944221167Sgnnvxge_dma_tags_create(vxge_vpath_t *vpath)
2945221167Sgnn{
2946221167Sgnn	int err = 0;
2947221167Sgnn	bus_size_t max_size, boundary;
2948221167Sgnn	vxge_dev_t *vdev = vpath->vdev;
2949221167Sgnn	ifnet_t ifp = vdev->ifp;
2950221167Sgnn
2951221167Sgnn	max_size = ifp->if_mtu +
2952221167Sgnn	    VXGE_HAL_MAC_HEADER_MAX_SIZE +
2953221167Sgnn	    VXGE_HAL_HEADER_ETHERNET_II_802_3_ALIGN;
2954221167Sgnn
2955221167Sgnn	VXGE_BUFFER_ALIGN(max_size, 128)
2956221167Sgnn	if (max_size <= MCLBYTES)
2957221167Sgnn		vdev->rx_mbuf_sz = MCLBYTES;
2958221167Sgnn	else
2959221167Sgnn		vdev->rx_mbuf_sz =
2960221167Sgnn		    (max_size > MJUMPAGESIZE) ? MJUM9BYTES : MJUMPAGESIZE;
2961221167Sgnn
2962221167Sgnn	boundary = (max_size > PAGE_SIZE) ? 0 : PAGE_SIZE;
2963221167Sgnn
2964221167Sgnn	/* DMA tag for Tx */
2965221167Sgnn	err = bus_dma_tag_create(
2966221167Sgnn	    bus_get_dma_tag(vdev->ndev),
2967221167Sgnn	    1,
2968221167Sgnn	    PAGE_SIZE,
2969221167Sgnn	    BUS_SPACE_MAXADDR,
2970221167Sgnn	    BUS_SPACE_MAXADDR,
2971221167Sgnn	    NULL,
2972221167Sgnn	    NULL,
2973221167Sgnn	    VXGE_TSO_SIZE,
2974221167Sgnn	    VXGE_MAX_SEGS,
2975221167Sgnn	    PAGE_SIZE,
2976221167Sgnn	    BUS_DMA_ALLOCNOW,
2977221167Sgnn	    NULL,
2978221167Sgnn	    NULL,
2979221167Sgnn	    &(vpath->dma_tag_tx));
2980221167Sgnn	if (err != 0)
2981221167Sgnn		goto _exit0;
2982221167Sgnn
2983221167Sgnn	/* DMA tag for Rx */
2984221167Sgnn	err = bus_dma_tag_create(
2985221167Sgnn	    bus_get_dma_tag(vdev->ndev),
2986221167Sgnn	    1,
2987221167Sgnn	    boundary,
2988221167Sgnn	    BUS_SPACE_MAXADDR,
2989221167Sgnn	    BUS_SPACE_MAXADDR,
2990221167Sgnn	    NULL,
2991221167Sgnn	    NULL,
2992221167Sgnn	    vdev->rx_mbuf_sz,
2993221167Sgnn	    1,
2994221167Sgnn	    vdev->rx_mbuf_sz,
2995221167Sgnn	    BUS_DMA_ALLOCNOW,
2996221167Sgnn	    NULL,
2997221167Sgnn	    NULL,
2998221167Sgnn	    &(vpath->dma_tag_rx));
2999221167Sgnn	if (err != 0)
3000221167Sgnn		goto _exit1;
3001221167Sgnn
3002221167Sgnn	/* Create DMA map for this descriptor */
3003221167Sgnn	err = bus_dmamap_create(vpath->dma_tag_rx, BUS_DMA_NOWAIT,
3004221167Sgnn	    &vpath->extra_dma_map);
3005221167Sgnn	if (err == 0)
3006221167Sgnn		goto _exit0;
3007221167Sgnn
3008221167Sgnn	bus_dma_tag_destroy(vpath->dma_tag_rx);
3009221167Sgnn
3010221167Sgnn_exit1:
3011221167Sgnn	bus_dma_tag_destroy(vpath->dma_tag_tx);
3012221167Sgnn
3013221167Sgnn_exit0:
3014221167Sgnn	return (err);
3015221167Sgnn}
3016221167Sgnn
3017221167Sgnnstatic inline int
3018221167Sgnnvxge_dma_mbuf_coalesce(bus_dma_tag_t dma_tag_tx, bus_dmamap_t dma_map,
3019221167Sgnn    mbuf_t * m_headp, bus_dma_segment_t * dma_buffers,
3020221167Sgnn    int *num_segs)
3021221167Sgnn{
3022221167Sgnn	int err = 0;
3023221167Sgnn	mbuf_t mbuf_pkt = NULL;
3024221167Sgnn
3025221167Sgnnretry:
3026221167Sgnn	err = bus_dmamap_load_mbuf_sg(dma_tag_tx, dma_map, *m_headp,
3027221167Sgnn	    dma_buffers, num_segs, BUS_DMA_NOWAIT);
3028221167Sgnn	if (err == EFBIG) {
3029221167Sgnn		/* try to defrag, too many segments */
3030221167Sgnn		mbuf_pkt = m_defrag(*m_headp, M_DONTWAIT);
3031221167Sgnn		if (mbuf_pkt == NULL) {
3032221167Sgnn			err = ENOBUFS;
3033221167Sgnn			goto _exit0;
3034221167Sgnn		}
3035221167Sgnn		*m_headp = mbuf_pkt;
3036221167Sgnn		goto retry;
3037221167Sgnn	}
3038221167Sgnn
3039221167Sgnn_exit0:
3040221167Sgnn	return (err);
3041221167Sgnn}
3042221167Sgnn
3043221167Sgnnint
3044221167Sgnnvxge_device_hw_info_get(vxge_dev_t *vdev)
3045221167Sgnn{
3046221167Sgnn	int i, err = ENXIO;
3047221167Sgnn	u64 vpath_mask = 0;
3048221167Sgnn	u32 max_supported_vpath = 0;
3049221167Sgnn	u32 fw_ver_maj_min;
3050221167Sgnn	vxge_firmware_upgrade_e fw_option;
3051221167Sgnn
3052221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
3053221167Sgnn	vxge_hal_device_hw_info_t *hw_info;
3054221167Sgnn
3055221167Sgnn	status = vxge_hal_device_hw_info_get(vdev->pdev,
3056221167Sgnn	    (pci_reg_h) vdev->pdev->reg_map[0],
3057221167Sgnn	    (u8 *) vdev->pdev->bar_info[0],
3058221167Sgnn	    &vdev->config.hw_info);
3059221167Sgnn
3060221167Sgnn	if (status != VXGE_HAL_OK)
3061221167Sgnn		goto _exit0;
3062221167Sgnn
3063221167Sgnn	hw_info = &vdev->config.hw_info;
3064221167Sgnn
3065221167Sgnn	vpath_mask = hw_info->vpath_mask;
3066221167Sgnn	if (vpath_mask == 0) {
3067221167Sgnn		device_printf(vdev->ndev, "No vpaths available in device\n");
3068221167Sgnn		goto _exit0;
3069221167Sgnn	}
3070221167Sgnn
3071221167Sgnn	fw_option = vdev->config.fw_option;
3072221167Sgnn
3073221167Sgnn	/* Check how many vpaths are available */
3074221167Sgnn	for (i = 0; i < VXGE_HAL_MAX_VIRTUAL_PATHS; i++) {
3075221167Sgnn		if (!((vpath_mask) & mBIT(i)))
3076221167Sgnn			continue;
3077221167Sgnn		max_supported_vpath++;
3078221167Sgnn	}
3079221167Sgnn
3080221167Sgnn	vdev->max_supported_vpath = max_supported_vpath;
3081221167Sgnn	status = vxge_hal_device_is_privileged(hw_info->host_type,
3082221167Sgnn	    hw_info->func_id);
3083221167Sgnn	vdev->is_privilaged = (status == VXGE_HAL_OK) ? TRUE : FALSE;
3084221167Sgnn
3085221167Sgnn	vdev->hw_fw_version = VXGE_FW_VERSION(
3086221167Sgnn	    hw_info->fw_version.major,
3087221167Sgnn	    hw_info->fw_version.minor,
3088221167Sgnn	    hw_info->fw_version.build);
3089221167Sgnn
3090221167Sgnn	fw_ver_maj_min =
3091221167Sgnn	    VXGE_FW_MAJ_MIN_VERSION(hw_info->fw_version.major,
3092221167Sgnn	    hw_info->fw_version.minor);
3093221167Sgnn
3094221167Sgnn	if ((fw_option >= VXGE_FW_UPGRADE_FORCE) ||
3095221167Sgnn	    (vdev->hw_fw_version != VXGE_DRV_FW_VERSION)) {
3096221167Sgnn
3097221167Sgnn		/* For fw_ver 1.8.1 and above ignore build number. */
3098221167Sgnn		if ((fw_option == VXGE_FW_UPGRADE_ALL) &&
3099221167Sgnn		    ((vdev->hw_fw_version >= VXGE_FW_VERSION(1, 8, 1)) &&
3100221167Sgnn		    (fw_ver_maj_min == VXGE_DRV_FW_MAJ_MIN_VERSION))) {
3101221167Sgnn			goto _exit1;
3102221167Sgnn		}
3103221167Sgnn
3104221167Sgnn		if (vdev->hw_fw_version < VXGE_BASE_FW_VERSION) {
3105221167Sgnn			device_printf(vdev->ndev,
3106221167Sgnn			    "Upgrade driver through vxge_update, "
3107221167Sgnn			    "Unable to load the driver.\n");
3108221167Sgnn			goto _exit0;
3109221167Sgnn		}
3110221167Sgnn		vdev->fw_upgrade = TRUE;
3111221167Sgnn	}
3112221167Sgnn
3113221167Sgnn_exit1:
3114221167Sgnn	err = 0;
3115221167Sgnn
3116221167Sgnn_exit0:
3117221167Sgnn	return (err);
3118221167Sgnn}
3119221167Sgnn
3120221167Sgnn/*
3121221167Sgnn * vxge_device_hw_info_print
3122221167Sgnn * Print device and driver information
3123221167Sgnn */
3124221167Sgnnvoid
3125221167Sgnnvxge_device_hw_info_print(vxge_dev_t *vdev)
3126221167Sgnn{
3127221167Sgnn	u32 i;
3128221167Sgnn	device_t ndev;
3129221167Sgnn	struct sysctl_ctx_list *ctx;
3130221167Sgnn	struct sysctl_oid_list *children;
3131221167Sgnn	char pmd_type[2][VXGE_PMD_INFO_LEN];
3132221167Sgnn
3133221167Sgnn	vxge_hal_device_t *hldev;
3134221167Sgnn	vxge_hal_device_hw_info_t *hw_info;
3135221167Sgnn	vxge_hal_device_pmd_info_t *pmd_port;
3136221167Sgnn
3137221167Sgnn	hldev = vdev->devh;
3138221167Sgnn	ndev = vdev->ndev;
3139221167Sgnn
3140221167Sgnn	ctx = device_get_sysctl_ctx(ndev);
3141221167Sgnn	children = SYSCTL_CHILDREN(device_get_sysctl_tree(ndev));
3142221167Sgnn
3143221167Sgnn	hw_info = &(vdev->config.hw_info);
3144221167Sgnn
3145221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_DRV_VERSION],
3146221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_DRV_VERSION]),
3147221167Sgnn	    "%d.%d.%d.%d", XGELL_VERSION_MAJOR, XGELL_VERSION_MINOR,
3148221167Sgnn	    XGELL_VERSION_FIX, XGELL_VERSION_BUILD);
3149221167Sgnn
3150221167Sgnn	/* Print PCI-e bus type/speed/width info */
3151221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_PCIE_INFO],
3152221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_PCIE_INFO]),
3153221167Sgnn	    "x%d", hldev->link_width);
3154221167Sgnn
3155221167Sgnn	if (hldev->link_width <= VXGE_HAL_PCI_E_LINK_WIDTH_X4)
3156221167Sgnn		device_printf(ndev, "For optimal performance a x8 "
3157221167Sgnn		    "PCI-Express slot is required.\n");
3158221167Sgnn
3159221167Sgnn	vxge_null_terminate((char *) hw_info->serial_number,
3160221167Sgnn	    sizeof(hw_info->serial_number));
3161221167Sgnn
3162221167Sgnn	vxge_null_terminate((char *) hw_info->part_number,
3163221167Sgnn	    sizeof(hw_info->part_number));
3164221167Sgnn
3165221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_SERIAL_NO],
3166221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_SERIAL_NO]),
3167221167Sgnn	    "%s", hw_info->serial_number);
3168221167Sgnn
3169221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_PART_NO],
3170221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_PART_NO]),
3171221167Sgnn	    "%s", hw_info->part_number);
3172221167Sgnn
3173221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_FW_VERSION],
3174221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_FW_VERSION]),
3175221167Sgnn	    "%s", hw_info->fw_version.version);
3176221167Sgnn
3177221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_FW_DATE],
3178221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_FW_DATE]),
3179221167Sgnn	    "%s", hw_info->fw_date.date);
3180221167Sgnn
3181221167Sgnn	pmd_port = &(hw_info->pmd_port0);
3182221167Sgnn	for (i = 0; i < hw_info->ports; i++) {
3183221167Sgnn
3184221167Sgnn		vxge_pmd_port_type_get(vdev, pmd_port->type,
3185221167Sgnn		    pmd_type[i], sizeof(pmd_type[i]));
3186221167Sgnn
3187221167Sgnn		strncpy(vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_0 + i],
3188221167Sgnn		    "vendor=??, sn=??, pn=??, type=??",
3189221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_0 + i]));
3190221167Sgnn
3191221167Sgnn		vxge_null_terminate(pmd_port->vendor, sizeof(pmd_port->vendor));
3192221167Sgnn		if (strlen(pmd_port->vendor) == 0) {
3193221167Sgnn			pmd_port = &(hw_info->pmd_port1);
3194221167Sgnn			continue;
3195221167Sgnn		}
3196221167Sgnn
3197221167Sgnn		vxge_null_terminate(pmd_port->ser_num,
3198221167Sgnn		    sizeof(pmd_port->ser_num));
3199221167Sgnn
3200221167Sgnn		vxge_null_terminate(pmd_port->part_num,
3201221167Sgnn		    sizeof(pmd_port->part_num));
3202221167Sgnn
3203221167Sgnn		snprintf(vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_0 + i],
3204221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_0 + i]),
3205221167Sgnn		    "vendor=%s, sn=%s, pn=%s, type=%s",
3206221167Sgnn		    pmd_port->vendor, pmd_port->ser_num,
3207221167Sgnn		    pmd_port->part_num, pmd_type[i]);
3208221167Sgnn
3209221167Sgnn		pmd_port = &(hw_info->pmd_port1);
3210221167Sgnn	}
3211221167Sgnn
3212221167Sgnn	switch (hw_info->function_mode) {
3213221167Sgnn	case VXGE_HAL_PCIE_FUNC_MODE_SF1_VP17:
3214221167Sgnn		snprintf(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE],
3215221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE]),
3216221167Sgnn		    "%s %d %s", "Single Function - 1 function(s)",
3217221167Sgnn		    vdev->max_supported_vpath, "VPath(s)/function");
3218221167Sgnn		break;
3219221167Sgnn
3220221167Sgnn	case VXGE_HAL_PCIE_FUNC_MODE_MF2_VP8:
3221221167Sgnn		snprintf(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE],
3222221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE]),
3223221167Sgnn		    "%s %d %s", "Multi Function - 2 function(s)",
3224221167Sgnn		    vdev->max_supported_vpath, "VPath(s)/function");
3225221167Sgnn		break;
3226221167Sgnn
3227221167Sgnn	case VXGE_HAL_PCIE_FUNC_MODE_MF4_VP4:
3228221167Sgnn		snprintf(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE],
3229221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE]),
3230221167Sgnn		    "%s %d %s", "Multi Function - 4 function(s)",
3231221167Sgnn		    vdev->max_supported_vpath, "VPath(s)/function");
3232221167Sgnn		break;
3233221167Sgnn
3234221167Sgnn	case VXGE_HAL_PCIE_FUNC_MODE_MF8_VP2:
3235221167Sgnn		snprintf(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE],
3236221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE]),
3237221167Sgnn		    "%s %d %s", "Multi Function - 8 function(s)",
3238221167Sgnn		    vdev->max_supported_vpath, "VPath(s)/function");
3239221167Sgnn		break;
3240221167Sgnn
3241221167Sgnn	case VXGE_HAL_PCIE_FUNC_MODE_MF8P_VP2:
3242221167Sgnn		snprintf(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE],
3243221167Sgnn		    sizeof(vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE]),
3244221167Sgnn		    "%s %d %s", "Multi Function (DirectIO) - 8 function(s)",
3245221167Sgnn		    vdev->max_supported_vpath, "VPath(s)/function");
3246221167Sgnn		break;
3247221167Sgnn	}
3248221167Sgnn
3249221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_INTR_MODE],
3250221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_INTR_MODE]),
3251221167Sgnn	    "%s", ((vdev->config.intr_mode == VXGE_HAL_INTR_MODE_MSIX) ?
3252221167Sgnn	    "MSI-X" : "INTA"));
3253221167Sgnn
3254221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_VPATH_COUNT],
3255221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_VPATH_COUNT]),
3256221167Sgnn	    "%d", vdev->no_of_vpath);
3257221167Sgnn
3258221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_MTU_SIZE],
3259221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_MTU_SIZE]),
3260221167Sgnn	    "%lu", vdev->ifp->if_mtu);
3261221167Sgnn
3262221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_LRO_MODE],
3263221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_LRO_MODE]),
3264221167Sgnn	    "%s", ((vdev->config.lro_enable) ? "Enabled" : "Disabled"));
3265221167Sgnn
3266221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_RTH_MODE],
3267221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_RTH_MODE]),
3268221167Sgnn	    "%s", ((vdev->config.rth_enable) ? "Enabled" : "Disabled"));
3269221167Sgnn
3270221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_TSO_MODE],
3271221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_TSO_MODE]),
3272221167Sgnn	    "%s", ((vdev->ifp->if_capenable & IFCAP_TSO4) ?
3273221167Sgnn	    "Enabled" : "Disabled"));
3274221167Sgnn
3275221167Sgnn	snprintf(vdev->config.nic_attr[VXGE_PRINT_ADAPTER_TYPE],
3276221167Sgnn	    sizeof(vdev->config.nic_attr[VXGE_PRINT_ADAPTER_TYPE]),
3277221167Sgnn	    "%s", ((hw_info->ports == 1) ? "Single Port" : "Dual Port"));
3278221167Sgnn
3279221167Sgnn	if (vdev->is_privilaged) {
3280221167Sgnn
3281221167Sgnn		if (hw_info->ports > 1) {
3282221167Sgnn
3283221167Sgnn			snprintf(vdev->config.nic_attr[VXGE_PRINT_PORT_MODE],
3284221167Sgnn			    sizeof(vdev->config.nic_attr[VXGE_PRINT_PORT_MODE]),
3285221167Sgnn			    "%s", vxge_port_mode[vdev->port_mode]);
3286221167Sgnn
3287221167Sgnn			if (vdev->port_mode != VXGE_HAL_DP_NP_MODE_SINGLE_PORT)
3288221167Sgnn				snprintf(vdev->config.nic_attr[VXGE_PRINT_PORT_FAILURE],
3289221167Sgnn				    sizeof(vdev->config.nic_attr[VXGE_PRINT_PORT_FAILURE]),
3290221167Sgnn				    "%s", vxge_port_failure[vdev->port_failure]);
3291221167Sgnn
3292221167Sgnn			vxge_active_port_update(vdev);
3293221167Sgnn			snprintf(vdev->config.nic_attr[VXGE_PRINT_ACTIVE_PORT],
3294221167Sgnn			    sizeof(vdev->config.nic_attr[VXGE_PRINT_ACTIVE_PORT]),
3295221167Sgnn			    "%lld", vdev->active_port);
3296221167Sgnn		}
3297221167Sgnn
3298221167Sgnn		if (!is_single_func(hw_info->function_mode)) {
3299221167Sgnn			snprintf(vdev->config.nic_attr[VXGE_PRINT_L2SWITCH_MODE],
3300221167Sgnn			    sizeof(vdev->config.nic_attr[VXGE_PRINT_L2SWITCH_MODE]),
3301221167Sgnn			    "%s", ((vdev->l2_switch) ? "Enabled" : "Disabled"));
3302221167Sgnn		}
3303221167Sgnn	}
3304221167Sgnn
3305221167Sgnn	device_printf(ndev, "Driver version\t: %s\n",
3306221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_DRV_VERSION]);
3307221167Sgnn
3308221167Sgnn	device_printf(ndev, "Serial number\t: %s\n",
3309221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_SERIAL_NO]);
3310221167Sgnn
3311221167Sgnn	device_printf(ndev, "Part number\t: %s\n",
3312221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_PART_NO]);
3313221167Sgnn
3314221167Sgnn	device_printf(ndev, "Firmware version\t: %s\n",
3315221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_FW_VERSION]);
3316221167Sgnn
3317221167Sgnn	device_printf(ndev, "Firmware date\t: %s\n",
3318221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_FW_DATE]);
3319221167Sgnn
3320221167Sgnn	device_printf(ndev, "Link width\t: %s\n",
3321221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_PCIE_INFO]);
3322221167Sgnn
3323221167Sgnn	if (vdev->is_privilaged) {
3324221167Sgnn		device_printf(ndev, "Function mode\t: %s\n",
3325221167Sgnn		    vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE]);
3326221167Sgnn	}
3327221167Sgnn
3328221167Sgnn	device_printf(ndev, "Interrupt type\t: %s\n",
3329221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_INTR_MODE]);
3330221167Sgnn
3331221167Sgnn	device_printf(ndev, "VPath(s) opened\t: %s\n",
3332221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_VPATH_COUNT]);
3333221167Sgnn
3334221167Sgnn	device_printf(ndev, "Adapter Type\t: %s\n",
3335221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_ADAPTER_TYPE]);
3336221167Sgnn
3337221167Sgnn	device_printf(ndev, "PMD Port 0\t: %s\n",
3338221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_0]);
3339221167Sgnn
3340221167Sgnn	if (hw_info->ports > 1) {
3341221167Sgnn		device_printf(ndev, "PMD Port 1\t: %s\n",
3342221167Sgnn		    vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_1]);
3343221167Sgnn
3344221167Sgnn		if (vdev->is_privilaged) {
3345221167Sgnn			device_printf(ndev, "Port Mode\t: %s\n",
3346221167Sgnn			    vdev->config.nic_attr[VXGE_PRINT_PORT_MODE]);
3347221167Sgnn
3348221167Sgnn			if (vdev->port_mode != VXGE_HAL_DP_NP_MODE_SINGLE_PORT)
3349221167Sgnn				device_printf(ndev, "Port Failure\t: %s\n",
3350221167Sgnn				    vdev->config.nic_attr[VXGE_PRINT_PORT_FAILURE]);
3351221167Sgnn
3352221167Sgnn			device_printf(vdev->ndev, "Active Port\t: %s\n",
3353221167Sgnn			    vdev->config.nic_attr[VXGE_PRINT_ACTIVE_PORT]);
3354221167Sgnn		}
3355221167Sgnn	}
3356221167Sgnn
3357221167Sgnn	if (vdev->is_privilaged && !is_single_func(hw_info->function_mode)) {
3358221167Sgnn		device_printf(vdev->ndev, "L2 Switch\t: %s\n",
3359221167Sgnn		    vdev->config.nic_attr[VXGE_PRINT_L2SWITCH_MODE]);
3360221167Sgnn	}
3361221167Sgnn
3362221167Sgnn	device_printf(ndev, "MTU is %s\n",
3363221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_MTU_SIZE]);
3364221167Sgnn
3365221167Sgnn	device_printf(ndev, "LRO %s\n",
3366221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_LRO_MODE]);
3367221167Sgnn
3368221167Sgnn	device_printf(ndev, "RTH %s\n",
3369221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_RTH_MODE]);
3370221167Sgnn
3371221167Sgnn	device_printf(ndev, "TSO %s\n",
3372221167Sgnn	    vdev->config.nic_attr[VXGE_PRINT_TSO_MODE]);
3373221167Sgnn
3374221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3375221167Sgnn	    OID_AUTO, "Driver version", CTLFLAG_RD,
3376221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_DRV_VERSION],
3377221167Sgnn	    0, "Driver version");
3378221167Sgnn
3379221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3380221167Sgnn	    OID_AUTO, "Serial number", CTLFLAG_RD,
3381221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_SERIAL_NO],
3382221167Sgnn	    0, "Serial number");
3383221167Sgnn
3384221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3385221167Sgnn	    OID_AUTO, "Part number", CTLFLAG_RD,
3386221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_PART_NO],
3387221167Sgnn	    0, "Part number");
3388221167Sgnn
3389221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3390221167Sgnn	    OID_AUTO, "Firmware version", CTLFLAG_RD,
3391221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_FW_VERSION],
3392221167Sgnn	    0, "Firmware version");
3393221167Sgnn
3394221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3395221167Sgnn	    OID_AUTO, "Firmware date", CTLFLAG_RD,
3396221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_FW_DATE],
3397221167Sgnn	    0, "Firmware date");
3398221167Sgnn
3399221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3400221167Sgnn	    OID_AUTO, "Link width", CTLFLAG_RD,
3401221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_PCIE_INFO],
3402221167Sgnn	    0, "Link width");
3403221167Sgnn
3404221167Sgnn	if (vdev->is_privilaged) {
3405221167Sgnn		SYSCTL_ADD_STRING(ctx, children,
3406221167Sgnn		    OID_AUTO, "Function mode", CTLFLAG_RD,
3407221167Sgnn		    &vdev->config.nic_attr[VXGE_PRINT_FUNC_MODE],
3408221167Sgnn		    0, "Function mode");
3409221167Sgnn	}
3410221167Sgnn
3411221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3412221167Sgnn	    OID_AUTO, "Interrupt type", CTLFLAG_RD,
3413221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_INTR_MODE],
3414221167Sgnn	    0, "Interrupt type");
3415221167Sgnn
3416221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3417221167Sgnn	    OID_AUTO, "VPath(s) opened", CTLFLAG_RD,
3418221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_VPATH_COUNT],
3419221167Sgnn	    0, "VPath(s) opened");
3420221167Sgnn
3421221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3422221167Sgnn	    OID_AUTO, "Adapter Type", CTLFLAG_RD,
3423221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_ADAPTER_TYPE],
3424221167Sgnn	    0, "Adapter Type");
3425221167Sgnn
3426221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3427221167Sgnn	    OID_AUTO, "pmd port 0", CTLFLAG_RD,
3428221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_0],
3429221167Sgnn	    0, "pmd port");
3430221167Sgnn
3431221167Sgnn	if (hw_info->ports > 1) {
3432221167Sgnn
3433221167Sgnn		SYSCTL_ADD_STRING(ctx, children,
3434221167Sgnn		    OID_AUTO, "pmd port 1", CTLFLAG_RD,
3435221167Sgnn		    &vdev->config.nic_attr[VXGE_PRINT_PMD_PORTS_1],
3436221167Sgnn		    0, "pmd port");
3437221167Sgnn
3438221167Sgnn		if (vdev->is_privilaged) {
3439221167Sgnn			SYSCTL_ADD_STRING(ctx, children,
3440221167Sgnn			    OID_AUTO, "Port Mode", CTLFLAG_RD,
3441221167Sgnn			    &vdev->config.nic_attr[VXGE_PRINT_PORT_MODE],
3442221167Sgnn			    0, "Port Mode");
3443221167Sgnn
3444221167Sgnn			if (vdev->port_mode != VXGE_HAL_DP_NP_MODE_SINGLE_PORT)
3445221167Sgnn				SYSCTL_ADD_STRING(ctx, children,
3446221167Sgnn				    OID_AUTO, "Port Failure", CTLFLAG_RD,
3447221167Sgnn				    &vdev->config.nic_attr[VXGE_PRINT_PORT_FAILURE],
3448221167Sgnn				    0, "Port Failure");
3449221167Sgnn
3450221167Sgnn			SYSCTL_ADD_STRING(ctx, children,
3451221167Sgnn			    OID_AUTO, "L2 Switch", CTLFLAG_RD,
3452221167Sgnn			    &vdev->config.nic_attr[VXGE_PRINT_L2SWITCH_MODE],
3453221167Sgnn			    0, "L2 Switch");
3454221167Sgnn		}
3455221167Sgnn	}
3456221167Sgnn
3457221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3458221167Sgnn	    OID_AUTO, "LRO mode", CTLFLAG_RD,
3459221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_LRO_MODE],
3460221167Sgnn	    0, "LRO mode");
3461221167Sgnn
3462221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3463221167Sgnn	    OID_AUTO, "RTH mode", CTLFLAG_RD,
3464221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_RTH_MODE],
3465221167Sgnn	    0, "RTH mode");
3466221167Sgnn
3467221167Sgnn	SYSCTL_ADD_STRING(ctx, children,
3468221167Sgnn	    OID_AUTO, "TSO mode", CTLFLAG_RD,
3469221167Sgnn	    &vdev->config.nic_attr[VXGE_PRINT_TSO_MODE],
3470221167Sgnn	    0, "TSO mode");
3471221167Sgnn}
3472221167Sgnn
3473221167Sgnnvoid
3474221167Sgnnvxge_pmd_port_type_get(vxge_dev_t *vdev, u32 port_type,
3475221167Sgnn    char *ifm_name, u8 ifm_len)
3476221167Sgnn{
3477221167Sgnn
3478221167Sgnn	vdev->ifm_optics = IFM_UNKNOWN;
3479221167Sgnn
3480221167Sgnn	switch (port_type) {
3481221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_SR:
3482221167Sgnn		vdev->ifm_optics = IFM_10G_SR;
3483221167Sgnn		strlcpy(ifm_name, "10GbE SR", ifm_len);
3484221167Sgnn		break;
3485221167Sgnn
3486221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_LR:
3487221167Sgnn		vdev->ifm_optics = IFM_10G_LR;
3488221167Sgnn		strlcpy(ifm_name, "10GbE LR", ifm_len);
3489221167Sgnn		break;
3490221167Sgnn
3491221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_LRM:
3492221167Sgnn		vdev->ifm_optics = IFM_10G_LRM;
3493221167Sgnn		strlcpy(ifm_name, "10GbE LRM", ifm_len);
3494221167Sgnn		break;
3495221167Sgnn
3496221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_DIRECT:
3497221167Sgnn		vdev->ifm_optics = IFM_10G_TWINAX;
3498221167Sgnn		strlcpy(ifm_name, "10GbE DA (Direct Attached)", ifm_len);
3499221167Sgnn		break;
3500221167Sgnn
3501221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_CX4:
3502221167Sgnn		vdev->ifm_optics = IFM_10G_CX4;
3503221167Sgnn		strlcpy(ifm_name, "10GbE CX4", ifm_len);
3504221167Sgnn		break;
3505221167Sgnn
3506221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_BASE_T:
3507221167Sgnn#if __FreeBSD_version >= 800000
3508221167Sgnn		vdev->ifm_optics = IFM_10G_T;
3509221167Sgnn#endif
3510221167Sgnn		strlcpy(ifm_name, "10GbE baseT", ifm_len);
3511221167Sgnn		break;
3512221167Sgnn
3513221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_10G_OTHER:
3514221167Sgnn		strlcpy(ifm_name, "10GbE Other", ifm_len);
3515221167Sgnn		break;
3516221167Sgnn
3517221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_SX:
3518221167Sgnn		vdev->ifm_optics = IFM_1000_SX;
3519221167Sgnn		strlcpy(ifm_name, "1GbE SX", ifm_len);
3520221167Sgnn		break;
3521221167Sgnn
3522221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_LX:
3523221167Sgnn		vdev->ifm_optics = IFM_1000_LX;
3524221167Sgnn		strlcpy(ifm_name, "1GbE LX", ifm_len);
3525221167Sgnn		break;
3526221167Sgnn
3527221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_CX:
3528221167Sgnn		vdev->ifm_optics = IFM_1000_CX;
3529221167Sgnn		strlcpy(ifm_name, "1GbE CX", ifm_len);
3530221167Sgnn		break;
3531221167Sgnn
3532221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_BASE_T:
3533221167Sgnn		vdev->ifm_optics = IFM_1000_T;
3534221167Sgnn		strlcpy(ifm_name, "1GbE baseT", ifm_len);
3535221167Sgnn		break;
3536221167Sgnn
3537221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_DIRECT:
3538221167Sgnn		strlcpy(ifm_name, "1GbE DA (Direct Attached)",
3539221167Sgnn		    ifm_len);
3540221167Sgnn		break;
3541221167Sgnn
3542221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_CX4:
3543221167Sgnn		strlcpy(ifm_name, "1GbE CX4", ifm_len);
3544221167Sgnn		break;
3545221167Sgnn
3546221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_1G_OTHER:
3547221167Sgnn		strlcpy(ifm_name, "1GbE Other", ifm_len);
3548221167Sgnn		break;
3549221167Sgnn
3550221167Sgnn	default:
3551221167Sgnn	case VXGE_HAL_DEVICE_PMD_TYPE_UNKNOWN:
3552221167Sgnn		strlcpy(ifm_name, "UNSUP", ifm_len);
3553221167Sgnn		break;
3554221167Sgnn	}
3555221167Sgnn}
3556221167Sgnn
3557221167Sgnnu32
3558221167Sgnnvxge_ring_length_get(u32 buffer_mode)
3559221167Sgnn{
3560221167Sgnn	return (VXGE_DEFAULT_RING_BLOCK *
3561221167Sgnn	    vxge_hal_ring_rxds_per_block_get(buffer_mode));
3562221167Sgnn}
3563221167Sgnn
3564221167Sgnn/*
3565221167Sgnn * Removes trailing spaces padded
3566221167Sgnn * and NULL terminates strings
3567221167Sgnn */
3568221167Sgnnstatic inline void
3569221167Sgnnvxge_null_terminate(char *str, size_t len)
3570221167Sgnn{
3571221167Sgnn	len--;
3572221167Sgnn	while (*str && (*str != ' ') && (len != 0))
3573221167Sgnn		++str;
3574221167Sgnn
3575221167Sgnn	--len;
3576221167Sgnn	if (*str)
3577221167Sgnn		*str = '\0';
3578221167Sgnn}
3579221167Sgnn
3580221167Sgnn/*
3581221167Sgnn * vxge_ioctl
3582221167Sgnn * Callback to control the device
3583221167Sgnn */
3584221167Sgnnint
3585221167Sgnnvxge_ioctl(ifnet_t ifp, u_long command, caddr_t data)
3586221167Sgnn{
3587221167Sgnn	int mask, err = 0;
3588221167Sgnn	vxge_dev_t *vdev = (vxge_dev_t *) ifp->if_softc;
3589221167Sgnn	struct ifreq *ifr = (struct ifreq *) data;
3590221167Sgnn
3591221167Sgnn	if (!vdev->is_active)
3592221167Sgnn		return (EBUSY);
3593221167Sgnn
3594221167Sgnn	switch (command) {
3595221167Sgnn		/* Set/Get ifnet address */
3596221167Sgnn	case SIOCSIFADDR:
3597221167Sgnn	case SIOCGIFADDR:
3598221167Sgnn		ether_ioctl(ifp, command, data);
3599221167Sgnn		break;
3600221167Sgnn
3601221167Sgnn		/* Set Interface MTU */
3602221167Sgnn	case SIOCSIFMTU:
3603221167Sgnn		err = vxge_change_mtu(vdev, (unsigned long)ifr->ifr_mtu);
3604221167Sgnn		break;
3605221167Sgnn
3606221167Sgnn		/* Set Interface Flags */
3607221167Sgnn	case SIOCSIFFLAGS:
3608221167Sgnn		VXGE_DRV_LOCK(vdev);
3609221167Sgnn		if (ifp->if_flags & IFF_UP) {
3610221167Sgnn			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
3611221167Sgnn				if ((ifp->if_flags ^ vdev->if_flags) &
3612221167Sgnn				    (IFF_PROMISC | IFF_ALLMULTI))
3613221167Sgnn					vxge_promisc_set(vdev);
3614221167Sgnn			} else {
3615221167Sgnn				vxge_init_locked(vdev);
3616221167Sgnn			}
3617221167Sgnn		} else {
3618221167Sgnn			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
3619221167Sgnn				vxge_stop_locked(vdev);
3620221167Sgnn		}
3621221167Sgnn		vdev->if_flags = ifp->if_flags;
3622221167Sgnn		VXGE_DRV_UNLOCK(vdev);
3623221167Sgnn		break;
3624221167Sgnn
3625221167Sgnn		/* Add/delete multicast address */
3626221167Sgnn	case SIOCADDMULTI:
3627221167Sgnn	case SIOCDELMULTI:
3628221167Sgnn		break;
3629221167Sgnn
3630221167Sgnn		/* Get/Set Interface Media */
3631221167Sgnn	case SIOCSIFMEDIA:
3632221167Sgnn	case SIOCGIFMEDIA:
3633221167Sgnn		err = ifmedia_ioctl(ifp, ifr, &vdev->media, command);
3634221167Sgnn		break;
3635221167Sgnn
3636221167Sgnn		/* Set Capabilities */
3637221167Sgnn	case SIOCSIFCAP:
3638221167Sgnn		VXGE_DRV_LOCK(vdev);
3639221167Sgnn		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
3640221167Sgnn
3641221167Sgnn		if (mask & IFCAP_TXCSUM) {
3642221167Sgnn			ifp->if_capenable ^= IFCAP_TXCSUM;
3643221167Sgnn			ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
3644221167Sgnn
3645221167Sgnn			if ((ifp->if_capenable & IFCAP_TSO) &&
3646221167Sgnn			    !(ifp->if_capenable & IFCAP_TXCSUM)) {
3647221167Sgnn
3648221167Sgnn				ifp->if_capenable &= ~IFCAP_TSO;
3649221167Sgnn				ifp->if_hwassist &= ~CSUM_TSO;
3650221167Sgnn				if_printf(ifp, "TSO Disabled\n");
3651221167Sgnn			}
3652221167Sgnn		}
3653221167Sgnn		if (mask & IFCAP_RXCSUM)
3654221167Sgnn			ifp->if_capenable ^= IFCAP_RXCSUM;
3655221167Sgnn
3656221167Sgnn		if (mask & IFCAP_TSO4) {
3657221167Sgnn			ifp->if_capenable ^= IFCAP_TSO4;
3658221167Sgnn
3659221167Sgnn			if (ifp->if_capenable & IFCAP_TSO) {
3660221167Sgnn				if (ifp->if_capenable & IFCAP_TXCSUM) {
3661221167Sgnn					ifp->if_hwassist |= CSUM_TSO;
3662221167Sgnn					if_printf(ifp, "TSO Enabled\n");
3663221167Sgnn				} else {
3664221167Sgnn					ifp->if_capenable &= ~IFCAP_TSO;
3665221167Sgnn					ifp->if_hwassist &= ~CSUM_TSO;
3666221167Sgnn					if_printf(ifp,
3667221167Sgnn					    "Enable tx checksum offload \
3668221167Sgnn					     first.\n");
3669221167Sgnn					err = EAGAIN;
3670221167Sgnn				}
3671221167Sgnn			} else {
3672221167Sgnn				ifp->if_hwassist &= ~CSUM_TSO;
3673221167Sgnn				if_printf(ifp, "TSO Disabled\n");
3674221167Sgnn			}
3675221167Sgnn		}
3676221167Sgnn		if (mask & IFCAP_LRO)
3677221167Sgnn			ifp->if_capenable ^= IFCAP_LRO;
3678221167Sgnn
3679221167Sgnn		if (mask & IFCAP_VLAN_HWTAGGING)
3680221167Sgnn			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
3681221167Sgnn
3682221167Sgnn		if (mask & IFCAP_VLAN_MTU)
3683221167Sgnn			ifp->if_capenable ^= IFCAP_VLAN_MTU;
3684221167Sgnn
3685221167Sgnn		if (mask & IFCAP_VLAN_HWCSUM)
3686221167Sgnn			ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
3687221167Sgnn
3688221167Sgnn#if __FreeBSD_version >= 800000
3689221167Sgnn		if (mask & IFCAP_VLAN_HWTSO)
3690221167Sgnn			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
3691221167Sgnn#endif
3692221167Sgnn
3693221167Sgnn#if defined(VLAN_CAPABILITIES)
3694221167Sgnn		VLAN_CAPABILITIES(ifp);
3695221167Sgnn#endif
3696221167Sgnn
3697221167Sgnn		VXGE_DRV_UNLOCK(vdev);
3698221167Sgnn		break;
3699221167Sgnn
3700221167Sgnn	case SIOCGPRIVATE_0:
3701221167Sgnn		VXGE_DRV_LOCK(vdev);
3702221167Sgnn		err = vxge_ioctl_stats(vdev, ifr);
3703221167Sgnn		VXGE_DRV_UNLOCK(vdev);
3704221167Sgnn		break;
3705221167Sgnn
3706221167Sgnn	case SIOCGPRIVATE_1:
3707221167Sgnn		VXGE_DRV_LOCK(vdev);
3708221167Sgnn		err = vxge_ioctl_regs(vdev, ifr);
3709221167Sgnn		VXGE_DRV_UNLOCK(vdev);
3710221167Sgnn		break;
3711221167Sgnn
3712221167Sgnn	default:
3713221167Sgnn		err = ether_ioctl(ifp, command, data);
3714221167Sgnn		break;
3715221167Sgnn	}
3716221167Sgnn
3717221167Sgnn	return (err);
3718221167Sgnn}
3719221167Sgnn
3720221167Sgnn/*
3721221167Sgnn * vxge_ioctl_regs
3722221167Sgnn * IOCTL to get registers
3723221167Sgnn */
3724221167Sgnnint
3725221167Sgnnvxge_ioctl_regs(vxge_dev_t *vdev, struct ifreq *ifr)
3726221167Sgnn{
3727221167Sgnn	u64 value = 0x0;
3728221167Sgnn	u32 vp_id = 0;
3729221167Sgnn	u32 offset, reqd_size = 0;
3730221167Sgnn	int i, err = EINVAL;
3731221167Sgnn
3732221167Sgnn	char *command = (char *) ifr->ifr_data;
3733221167Sgnn	void *reg_info = (void *) ifr->ifr_data;
3734221167Sgnn
3735221167Sgnn	vxge_vpath_t *vpath;
3736221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
3737221167Sgnn	vxge_hal_mgmt_reg_type_e regs_type;
3738221167Sgnn
3739221167Sgnn	switch (*command) {
3740221167Sgnn	case vxge_hal_mgmt_reg_type_pcicfgmgmt:
3741221167Sgnn		if (vdev->is_privilaged) {
3742221167Sgnn			reqd_size = sizeof(vxge_hal_pcicfgmgmt_reg_t);
3743221167Sgnn			regs_type = vxge_hal_mgmt_reg_type_pcicfgmgmt;
3744221167Sgnn		}
3745221167Sgnn		break;
3746221167Sgnn
3747221167Sgnn	case vxge_hal_mgmt_reg_type_mrpcim:
3748221167Sgnn		if (vdev->is_privilaged) {
3749221167Sgnn			reqd_size = sizeof(vxge_hal_mrpcim_reg_t);
3750221167Sgnn			regs_type = vxge_hal_mgmt_reg_type_mrpcim;
3751221167Sgnn		}
3752221167Sgnn		break;
3753221167Sgnn
3754221167Sgnn	case vxge_hal_mgmt_reg_type_srpcim:
3755221167Sgnn		if (vdev->is_privilaged) {
3756221167Sgnn			reqd_size = sizeof(vxge_hal_srpcim_reg_t);
3757221167Sgnn			regs_type = vxge_hal_mgmt_reg_type_srpcim;
3758221167Sgnn		}
3759221167Sgnn		break;
3760221167Sgnn
3761221167Sgnn	case vxge_hal_mgmt_reg_type_memrepair:
3762221167Sgnn		if (vdev->is_privilaged) {
3763221167Sgnn			/* reqd_size = sizeof(vxge_hal_memrepair_reg_t); */
3764221167Sgnn			regs_type = vxge_hal_mgmt_reg_type_memrepair;
3765221167Sgnn		}
3766221167Sgnn		break;
3767221167Sgnn
3768221167Sgnn	case vxge_hal_mgmt_reg_type_legacy:
3769221167Sgnn		reqd_size = sizeof(vxge_hal_legacy_reg_t);
3770221167Sgnn		regs_type = vxge_hal_mgmt_reg_type_legacy;
3771221167Sgnn		break;
3772221167Sgnn
3773221167Sgnn	case vxge_hal_mgmt_reg_type_toc:
3774221167Sgnn		reqd_size = sizeof(vxge_hal_toc_reg_t);
3775221167Sgnn		regs_type = vxge_hal_mgmt_reg_type_toc;
3776221167Sgnn		break;
3777221167Sgnn
3778221167Sgnn	case vxge_hal_mgmt_reg_type_common:
3779221167Sgnn		reqd_size = sizeof(vxge_hal_common_reg_t);
3780221167Sgnn		regs_type = vxge_hal_mgmt_reg_type_common;
3781221167Sgnn		break;
3782221167Sgnn
3783221167Sgnn	case vxge_hal_mgmt_reg_type_vpmgmt:
3784221167Sgnn		reqd_size = sizeof(vxge_hal_vpmgmt_reg_t);
3785221167Sgnn		regs_type = vxge_hal_mgmt_reg_type_vpmgmt;
3786221167Sgnn		vpath = &(vdev->vpaths[*((u32 *) reg_info + 1)]);
3787221167Sgnn		vp_id = vpath->vp_id;
3788221167Sgnn		break;
3789221167Sgnn
3790221167Sgnn	case vxge_hal_mgmt_reg_type_vpath:
3791221167Sgnn		reqd_size = sizeof(vxge_hal_vpath_reg_t);
3792221167Sgnn		regs_type = vxge_hal_mgmt_reg_type_vpath;
3793221167Sgnn		vpath = &(vdev->vpaths[*((u32 *) reg_info + 1)]);
3794221167Sgnn		vp_id = vpath->vp_id;
3795221167Sgnn		break;
3796221167Sgnn
3797221167Sgnn	case VXGE_GET_VPATH_COUNT:
3798221167Sgnn		*((u32 *) reg_info) = vdev->no_of_vpath;
3799221167Sgnn		err = 0;
3800221167Sgnn		break;
3801221167Sgnn
3802221167Sgnn	default:
3803221167Sgnn		reqd_size = 0;
3804221167Sgnn		break;
3805221167Sgnn	}
3806221167Sgnn
3807221167Sgnn	if (reqd_size) {
3808221167Sgnn		for (i = 0, offset = 0; offset < reqd_size;
3809221167Sgnn		    i++, offset += 0x0008) {
3810221167Sgnn			value = 0x0;
3811221167Sgnn			status = vxge_hal_mgmt_reg_read(vdev->devh, regs_type,
3812221167Sgnn			    vp_id, offset, &value);
3813221167Sgnn
3814221167Sgnn			err = (status != VXGE_HAL_OK) ? EINVAL : 0;
3815221167Sgnn			if (err == EINVAL)
3816221167Sgnn				break;
3817221167Sgnn
3818221167Sgnn			*((u64 *) ((u64 *) reg_info + i)) = value;
3819221167Sgnn		}
3820221167Sgnn	}
3821221167Sgnn	return (err);
3822221167Sgnn}
3823221167Sgnn
3824221167Sgnn/*
3825221167Sgnn * vxge_ioctl_stats
3826221167Sgnn * IOCTL to get statistics
3827221167Sgnn */
3828221167Sgnnint
3829221167Sgnnvxge_ioctl_stats(vxge_dev_t *vdev, struct ifreq *ifr)
3830221167Sgnn{
3831221167Sgnn	int i, retsize, err = EINVAL;
3832221167Sgnn	u32 bufsize;
3833221167Sgnn
3834221167Sgnn	vxge_vpath_t *vpath;
3835221167Sgnn	vxge_bw_info_t *bw_info;
3836221167Sgnn	vxge_port_info_t *port_info;
3837221167Sgnn	vxge_drv_stats_t *drv_stat;
3838221167Sgnn
3839221167Sgnn	char *buffer = NULL;
3840221167Sgnn	char *command = (char *) ifr->ifr_data;
3841221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
3842221167Sgnn
3843221167Sgnn	switch (*command) {
3844221167Sgnn	case VXGE_GET_PCI_CONF:
3845221167Sgnn		bufsize = VXGE_STATS_BUFFER_SIZE;
3846221167Sgnn		buffer = (char *) vxge_mem_alloc(bufsize);
3847221167Sgnn		if (buffer != NULL) {
3848221167Sgnn			status = vxge_hal_aux_pci_config_read(vdev->devh,
3849221167Sgnn			    bufsize, buffer, &retsize);
3850221167Sgnn			if (status == VXGE_HAL_OK)
3851221167Sgnn				err = copyout(buffer, ifr->ifr_data, retsize);
3852221167Sgnn			else
3853221167Sgnn				device_printf(vdev->ndev,
3854221167Sgnn				    "failed pciconfig statistics query\n");
3855221167Sgnn
3856221167Sgnn			vxge_mem_free(buffer, bufsize);
3857221167Sgnn		}
3858221167Sgnn		break;
3859221167Sgnn
3860221167Sgnn	case VXGE_GET_MRPCIM_STATS:
3861221167Sgnn		if (!vdev->is_privilaged)
3862221167Sgnn			break;
3863221167Sgnn
3864221167Sgnn		bufsize = VXGE_STATS_BUFFER_SIZE;
3865221167Sgnn		buffer = (char *) vxge_mem_alloc(bufsize);
3866221167Sgnn		if (buffer != NULL) {
3867221167Sgnn			status = vxge_hal_aux_stats_mrpcim_read(vdev->devh,
3868221167Sgnn			    bufsize, buffer, &retsize);
3869221167Sgnn			if (status == VXGE_HAL_OK)
3870221167Sgnn				err = copyout(buffer, ifr->ifr_data, retsize);
3871221167Sgnn			else
3872221167Sgnn				device_printf(vdev->ndev,
3873221167Sgnn				    "failed mrpcim statistics query\n");
3874221167Sgnn
3875221167Sgnn			vxge_mem_free(buffer, bufsize);
3876221167Sgnn		}
3877221167Sgnn		break;
3878221167Sgnn
3879221167Sgnn	case VXGE_GET_DEVICE_STATS:
3880221167Sgnn		bufsize = VXGE_STATS_BUFFER_SIZE;
3881221167Sgnn		buffer = (char *) vxge_mem_alloc(bufsize);
3882221167Sgnn		if (buffer != NULL) {
3883221167Sgnn			status = vxge_hal_aux_stats_device_read(vdev->devh,
3884221167Sgnn			    bufsize, buffer, &retsize);
3885221167Sgnn			if (status == VXGE_HAL_OK)
3886221167Sgnn				err = copyout(buffer, ifr->ifr_data, retsize);
3887221167Sgnn			else
3888221167Sgnn				device_printf(vdev->ndev,
3889221167Sgnn				    "failed device statistics query\n");
3890221167Sgnn
3891221167Sgnn			vxge_mem_free(buffer, bufsize);
3892221167Sgnn		}
3893221167Sgnn		break;
3894221167Sgnn
3895221167Sgnn	case VXGE_GET_DEVICE_HWINFO:
3896221167Sgnn		bufsize = sizeof(vxge_device_hw_info_t);
3897221167Sgnn		buffer = (char *) vxge_mem_alloc(bufsize);
3898221167Sgnn		if (buffer != NULL) {
3899221167Sgnn			vxge_os_memcpy(
3900221167Sgnn			    &(((vxge_device_hw_info_t *) buffer)->hw_info),
3901221167Sgnn			    &vdev->config.hw_info,
3902221167Sgnn			    sizeof(vxge_hal_device_hw_info_t));
3903221167Sgnn
3904221167Sgnn			((vxge_device_hw_info_t *) buffer)->port_mode =
3905221167Sgnn			    vdev->port_mode;
3906221167Sgnn
3907221167Sgnn			((vxge_device_hw_info_t *) buffer)->port_failure =
3908221167Sgnn			    vdev->port_failure;
3909221167Sgnn
3910221167Sgnn			err = copyout(buffer, ifr->ifr_data, bufsize);
3911221167Sgnn			if (err != 0)
3912221167Sgnn				device_printf(vdev->ndev,
3913221167Sgnn				    "failed device hardware info query\n");
3914221167Sgnn
3915221167Sgnn			vxge_mem_free(buffer, bufsize);
3916221167Sgnn		}
3917221167Sgnn		break;
3918221167Sgnn
3919221167Sgnn	case VXGE_GET_DRIVER_STATS:
3920221167Sgnn		bufsize = sizeof(vxge_drv_stats_t) * vdev->no_of_vpath;
3921221167Sgnn		drv_stat = (vxge_drv_stats_t *) vxge_mem_alloc(bufsize);
3922221167Sgnn		if (drv_stat != NULL) {
3923221167Sgnn			for (i = 0; i < vdev->no_of_vpath; i++) {
3924221167Sgnn				vpath = &(vdev->vpaths[i]);
3925221167Sgnn
3926221167Sgnn				vpath->driver_stats.rx_lro_queued +=
3927221167Sgnn				    vpath->lro.lro_queued;
3928221167Sgnn
3929221167Sgnn				vpath->driver_stats.rx_lro_flushed +=
3930221167Sgnn				    vpath->lro.lro_flushed;
3931221167Sgnn
3932221167Sgnn				vxge_os_memcpy(&drv_stat[i],
3933221167Sgnn				    &(vpath->driver_stats),
3934221167Sgnn				    sizeof(vxge_drv_stats_t));
3935221167Sgnn			}
3936221167Sgnn
3937221167Sgnn			err = copyout(drv_stat, ifr->ifr_data, bufsize);
3938221167Sgnn			if (err != 0)
3939221167Sgnn				device_printf(vdev->ndev,
3940221167Sgnn				    "failed driver statistics query\n");
3941221167Sgnn
3942221167Sgnn			vxge_mem_free(drv_stat, bufsize);
3943221167Sgnn		}
3944221167Sgnn		break;
3945221167Sgnn
3946221167Sgnn	case VXGE_GET_BANDWIDTH:
3947221167Sgnn		bw_info = (vxge_bw_info_t *) ifr->ifr_data;
3948221167Sgnn
3949221167Sgnn		if ((vdev->config.hw_info.func_id != 0) &&
3950221167Sgnn		    (vdev->hw_fw_version < VXGE_FW_VERSION(1, 8, 0)))
3951221167Sgnn			break;
3952221167Sgnn
3953221167Sgnn		if (vdev->config.hw_info.func_id != 0)
3954221167Sgnn			bw_info->func_id = vdev->config.hw_info.func_id;
3955221167Sgnn
3956221167Sgnn		status = vxge_bw_priority_get(vdev, bw_info);
3957221167Sgnn		if (status != VXGE_HAL_OK)
3958221167Sgnn			break;
3959221167Sgnn
3960221167Sgnn		err = copyout(bw_info, ifr->ifr_data, sizeof(vxge_bw_info_t));
3961221167Sgnn		break;
3962221167Sgnn
3963221167Sgnn	case VXGE_SET_BANDWIDTH:
3964221167Sgnn		if (vdev->is_privilaged)
3965221167Sgnn			err = vxge_bw_priority_set(vdev, ifr);
3966221167Sgnn		break;
3967221167Sgnn
3968221167Sgnn	case VXGE_SET_PORT_MODE:
3969221167Sgnn		if (vdev->is_privilaged) {
3970221167Sgnn			if (vdev->config.hw_info.ports == VXGE_DUAL_PORT_MODE) {
3971221167Sgnn				port_info = (vxge_port_info_t *) ifr->ifr_data;
3972221167Sgnn				vdev->config.port_mode = port_info->port_mode;
3973221167Sgnn				err = vxge_port_mode_update(vdev);
3974221167Sgnn				if (err != ENXIO)
3975221167Sgnn					err = VXGE_HAL_FAIL;
3976221167Sgnn				else {
3977221167Sgnn					err = VXGE_HAL_OK;
3978221167Sgnn					device_printf(vdev->ndev,
3979221167Sgnn					    "PLEASE POWER CYCLE THE SYSTEM\n");
3980221167Sgnn				}
3981221167Sgnn			}
3982221167Sgnn		}
3983221167Sgnn		break;
3984221167Sgnn
3985221167Sgnn	case VXGE_GET_PORT_MODE:
3986221167Sgnn		if (vdev->is_privilaged) {
3987221167Sgnn			if (vdev->config.hw_info.ports == VXGE_DUAL_PORT_MODE) {
3988221167Sgnn				port_info = (vxge_port_info_t *) ifr->ifr_data;
3989221167Sgnn				err = vxge_port_mode_get(vdev, port_info);
3990221167Sgnn				if (err == VXGE_HAL_OK) {
3991221167Sgnn					err = copyout(port_info, ifr->ifr_data,
3992221167Sgnn					    sizeof(vxge_port_info_t));
3993221167Sgnn				}
3994221167Sgnn			}
3995221167Sgnn		}
3996221167Sgnn		break;
3997221167Sgnn
3998221167Sgnn	default:
3999221167Sgnn		break;
4000221167Sgnn	}
4001221167Sgnn
4002221167Sgnn	return (err);
4003221167Sgnn}
4004221167Sgnn
4005221167Sgnnint
4006221167Sgnnvxge_bw_priority_config(vxge_dev_t *vdev)
4007221167Sgnn{
4008221167Sgnn	u32 i;
4009221167Sgnn	int err = EINVAL;
4010221167Sgnn
4011221167Sgnn	for (i = 0; i < vdev->no_of_func; i++) {
4012221167Sgnn		err = vxge_bw_priority_update(vdev, i, TRUE);
4013221167Sgnn		if (err != 0)
4014221167Sgnn			break;
4015221167Sgnn	}
4016221167Sgnn
4017221167Sgnn	return (err);
4018221167Sgnn}
4019221167Sgnn
4020221167Sgnnint
4021221167Sgnnvxge_bw_priority_set(vxge_dev_t *vdev, struct ifreq *ifr)
4022221167Sgnn{
4023221167Sgnn	int err;
4024221167Sgnn	u32 func_id;
4025221167Sgnn	vxge_bw_info_t *bw_info;
4026221167Sgnn
4027221167Sgnn	bw_info = (vxge_bw_info_t *) ifr->ifr_data;
4028221167Sgnn	func_id = bw_info->func_id;
4029221167Sgnn
4030221167Sgnn	vdev->config.bw_info[func_id].priority = bw_info->priority;
4031221167Sgnn	vdev->config.bw_info[func_id].bandwidth = bw_info->bandwidth;
4032221167Sgnn
4033221167Sgnn	err = vxge_bw_priority_update(vdev, func_id, FALSE);
4034221167Sgnn
4035221167Sgnn	return (err);
4036221167Sgnn}
4037221167Sgnn
4038221167Sgnnint
4039221167Sgnnvxge_bw_priority_update(vxge_dev_t *vdev, u32 func_id, bool binit)
4040221167Sgnn{
4041221167Sgnn	u32 i, set = 0;
4042221167Sgnn	u32 bandwidth, priority, vpath_count;
4043221167Sgnn	u64 vpath_list[VXGE_HAL_MAX_VIRTUAL_PATHS];
4044221167Sgnn
4045221167Sgnn	vxge_hal_device_t *hldev;
4046221167Sgnn	vxge_hal_vp_config_t *vp_config;
4047221167Sgnn	vxge_hal_status_e status = VXGE_HAL_OK;
4048221167Sgnn
4049221167Sgnn	hldev = vdev->devh;
4050221167Sgnn
4051221167Sgnn	status = vxge_hal_get_vpath_list(vdev->devh, func_id,
4052221167Sgnn	    vpath_list, &vpath_count);
4053221167Sgnn
4054221167Sgnn	if (status != VXGE_HAL_OK)
4055221167Sgnn		return (status);
4056221167Sgnn
4057221167Sgnn	for (i = 0; i < vpath_count; i++) {
4058221167Sgnn		vp_config = &(hldev->config.vp_config[vpath_list[i]]);
4059221167Sgnn
4060221167Sgnn		/* Configure Bandwidth */
4061221167Sgnn		if (vdev->config.bw_info[func_id].bandwidth !=
4062221167Sgnn		    VXGE_HAL_VPATH_BW_LIMIT_DEFAULT) {
4063221167Sgnn
4064221167Sgnn			set = 1;
4065221167Sgnn			bandwidth = vdev->config.bw_info[func_id].bandwidth;
4066221167Sgnn			if (bandwidth < VXGE_HAL_VPATH_BW_LIMIT_MIN ||
4067221167Sgnn			    bandwidth > VXGE_HAL_VPATH_BW_LIMIT_MAX) {
4068221167Sgnn
4069221167Sgnn				bandwidth = VXGE_HAL_VPATH_BW_LIMIT_DEFAULT;
4070221167Sgnn			}
4071221167Sgnn			vp_config->bandwidth = bandwidth;
4072221167Sgnn		}
4073221167Sgnn
4074221167Sgnn		/*
4075221167Sgnn		 * If b/w limiting is enabled on any of the
4076221167Sgnn		 * VFs, then for remaining VFs set the priority to 3
4077221167Sgnn		 * and b/w limiting to max i.e 10 Gb)
4078221167Sgnn		 */
4079221167Sgnn		if (vp_config->bandwidth == VXGE_HAL_VPATH_BW_LIMIT_DEFAULT)
4080221167Sgnn			vp_config->bandwidth = VXGE_HAL_VPATH_BW_LIMIT_MAX;
4081221167Sgnn
4082221167Sgnn		if (binit && vdev->config.low_latency) {
4083221167Sgnn			if (func_id == 0)
4084221167Sgnn				vdev->config.bw_info[func_id].priority =
4085221167Sgnn				    VXGE_DEFAULT_VPATH_PRIORITY_HIGH;
4086221167Sgnn		}
4087221167Sgnn
4088221167Sgnn		/* Configure Priority */
4089221167Sgnn		if (vdev->config.bw_info[func_id].priority !=
4090221167Sgnn		    VXGE_HAL_VPATH_PRIORITY_DEFAULT) {
4091221167Sgnn
4092221167Sgnn			set = 1;
4093221167Sgnn			priority = vdev->config.bw_info[func_id].priority;
4094221167Sgnn			if (priority < VXGE_HAL_VPATH_PRIORITY_MIN ||
4095221167Sgnn			    priority > VXGE_HAL_VPATH_PRIORITY_MAX) {
4096221167Sgnn
4097221167Sgnn				priority = VXGE_HAL_VPATH_PRIORITY_DEFAULT;
4098221167Sgnn			}
4099221167Sgnn			vp_config->priority = priority;
4100221167Sgnn
4101221167Sgnn		} else if (vdev->config.low_latency) {
4102221167Sgnn			set = 1;
4103221167Sgnn			vp_config->priority = VXGE_DEFAULT_VPATH_PRIORITY_LOW;
4104221167Sgnn		}
4105221167Sgnn
4106221167Sgnn		if (set == 1) {
4107221167Sgnn			status = vxge_hal_rx_bw_priority_set(vdev->devh,
4108221167Sgnn			    vpath_list[i]);
4109221167Sgnn			if (status != VXGE_HAL_OK)
4110221167Sgnn				break;
4111221167Sgnn
4112221167Sgnn			if (vpath_list[i] < VXGE_HAL_TX_BW_VPATH_LIMIT) {
4113221167Sgnn				status = vxge_hal_tx_bw_priority_set(
4114221167Sgnn				    vdev->devh, vpath_list[i]);
4115221167Sgnn				if (status != VXGE_HAL_OK)
4116221167Sgnn					break;
4117221167Sgnn			}
4118221167Sgnn		}
4119221167Sgnn	}
4120221167Sgnn
4121221167Sgnn	return ((status  == VXGE_HAL_OK) ? 0 : EINVAL);
4122221167Sgnn}
4123221167Sgnn
4124221167Sgnn/*
4125221167Sgnn * vxge_intr_coalesce_tx
4126221167Sgnn * Changes interrupt coalescing if the interrupts are not within a range
4127221167Sgnn * Return Value: Nothing
4128221167Sgnn */
4129221167Sgnnvoid
4130221167Sgnnvxge_intr_coalesce_tx(vxge_vpath_t *vpath)
4131221167Sgnn{
4132221167Sgnn	u32 timer;
4133221167Sgnn
4134221167Sgnn	if (!vpath->tx_intr_coalesce)
4135221167Sgnn		return;
4136221167Sgnn
4137221167Sgnn	vpath->tx_interrupts++;
4138221167Sgnn	if (ticks > vpath->tx_ticks + hz/100) {
4139221167Sgnn
4140221167Sgnn		vpath->tx_ticks = ticks;
4141221167Sgnn		timer = vpath->tti_rtimer_val;
4142221167Sgnn		if (vpath->tx_interrupts > VXGE_MAX_TX_INTERRUPT_COUNT) {
4143221167Sgnn			if (timer != VXGE_TTI_RTIMER_ADAPT_VAL) {
4144221167Sgnn				vpath->tti_rtimer_val =
4145221167Sgnn				    VXGE_TTI_RTIMER_ADAPT_VAL;
4146221167Sgnn
4147221167Sgnn				vxge_hal_vpath_dynamic_tti_rtimer_set(
4148221167Sgnn				    vpath->handle, vpath->tti_rtimer_val);
4149221167Sgnn			}
4150221167Sgnn		} else {
4151221167Sgnn			if (timer != 0) {
4152221167Sgnn				vpath->tti_rtimer_val = 0;
4153221167Sgnn				vxge_hal_vpath_dynamic_tti_rtimer_set(
4154221167Sgnn				    vpath->handle, vpath->tti_rtimer_val);
4155221167Sgnn			}
4156221167Sgnn		}
4157221167Sgnn		vpath->tx_interrupts = 0;
4158221167Sgnn	}
4159221167Sgnn}
4160221167Sgnn
4161221167Sgnn/*
4162221167Sgnn * vxge_intr_coalesce_rx
4163221167Sgnn * Changes interrupt coalescing if the interrupts are not within a range
4164221167Sgnn * Return Value: Nothing
4165221167Sgnn */
4166221167Sgnnvoid
4167221167Sgnnvxge_intr_coalesce_rx(vxge_vpath_t *vpath)
4168221167Sgnn{
4169221167Sgnn	u32 timer;
4170221167Sgnn
4171221167Sgnn	if (!vpath->rx_intr_coalesce)
4172221167Sgnn		return;
4173221167Sgnn
4174221167Sgnn	vpath->rx_interrupts++;
4175221167Sgnn	if (ticks > vpath->rx_ticks + hz/100) {
4176221167Sgnn
4177221167Sgnn		vpath->rx_ticks = ticks;
4178221167Sgnn		timer = vpath->rti_rtimer_val;
4179221167Sgnn
4180221167Sgnn		if (vpath->rx_interrupts > VXGE_MAX_RX_INTERRUPT_COUNT) {
4181221167Sgnn			if (timer != VXGE_RTI_RTIMER_ADAPT_VAL) {
4182221167Sgnn				vpath->rti_rtimer_val =
4183221167Sgnn				    VXGE_RTI_RTIMER_ADAPT_VAL;
4184221167Sgnn
4185221167Sgnn				vxge_hal_vpath_dynamic_rti_rtimer_set(
4186221167Sgnn				    vpath->handle, vpath->rti_rtimer_val);
4187221167Sgnn			}
4188221167Sgnn		} else {
4189221167Sgnn			if (timer != 0) {
4190221167Sgnn				vpath->rti_rtimer_val = 0;
4191221167Sgnn				vxge_hal_vpath_dynamic_rti_rtimer_set(
4192221167Sgnn				    vpath->handle, vpath->rti_rtimer_val);
4193221167Sgnn			}
4194221167Sgnn		}
4195221167Sgnn		vpath->rx_interrupts = 0;
4196221167Sgnn	}
4197221167Sgnn}
4198221167Sgnn
4199221167Sgnn/*
4200221167Sgnn * vxge_methods FreeBSD device interface entry points
4201221167Sgnn */
4202221167Sgnnstatic device_method_t vxge_methods[] = {
4203221167Sgnn	DEVMETHOD(device_probe, vxge_probe),
4204221167Sgnn	DEVMETHOD(device_attach, vxge_attach),
4205221167Sgnn	DEVMETHOD(device_detach, vxge_detach),
4206221167Sgnn	DEVMETHOD(device_shutdown, vxge_shutdown),
4207221167Sgnn	{0, 0}
4208221167Sgnn};
4209221167Sgnn
4210221167Sgnnstatic driver_t vxge_driver = {
4211221167Sgnn	"vxge", vxge_methods, sizeof(vxge_dev_t),
4212221167Sgnn};
4213221167Sgnn
4214221167Sgnnstatic devclass_t vxge_devclass;
4215221167Sgnn
4216221167SgnnDRIVER_MODULE(vxge, pci, vxge_driver, vxge_devclass, 0, 0);
4217