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