xref: /freebsd/sys/dev/qlnx/qlnxe/qlnx_os.c (revision 1eaecc214ea2bfde84f4194c1d0e20b18117343f)
111e25f0dSDavid C Somayajulu /*
211e25f0dSDavid C Somayajulu  * Copyright (c) 2017-2018 Cavium, Inc.
311e25f0dSDavid C Somayajulu  * All rights reserved.
411e25f0dSDavid C Somayajulu  *
511e25f0dSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
611e25f0dSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
711e25f0dSDavid C Somayajulu  *  are met:
811e25f0dSDavid C Somayajulu  *
911e25f0dSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
1011e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
1111e25f0dSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
1211e25f0dSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
1311e25f0dSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
1411e25f0dSDavid C Somayajulu  *
1511e25f0dSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1611e25f0dSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1711e25f0dSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1811e25f0dSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
1911e25f0dSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2011e25f0dSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2111e25f0dSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2211e25f0dSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2311e25f0dSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2411e25f0dSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2511e25f0dSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
2611e25f0dSDavid C Somayajulu  */
2711e25f0dSDavid C Somayajulu 
2811e25f0dSDavid C Somayajulu /*
2911e25f0dSDavid C Somayajulu  * File: qlnx_os.c
3011e25f0dSDavid C Somayajulu  * Author : David C Somayajulu, Cavium, Inc., San Jose, CA 95131.
3111e25f0dSDavid C Somayajulu  */
3211e25f0dSDavid C Somayajulu 
3311e25f0dSDavid C Somayajulu #include <sys/cdefs.h>
3411e25f0dSDavid C Somayajulu #include "qlnx_os.h"
3511e25f0dSDavid C Somayajulu #include "bcm_osal.h"
3611e25f0dSDavid C Somayajulu #include "reg_addr.h"
3711e25f0dSDavid C Somayajulu #include "ecore_gtt_reg_addr.h"
3811e25f0dSDavid C Somayajulu #include "ecore.h"
3911e25f0dSDavid C Somayajulu #include "ecore_chain.h"
4011e25f0dSDavid C Somayajulu #include "ecore_status.h"
4111e25f0dSDavid C Somayajulu #include "ecore_hw.h"
4211e25f0dSDavid C Somayajulu #include "ecore_rt_defs.h"
4311e25f0dSDavid C Somayajulu #include "ecore_init_ops.h"
4411e25f0dSDavid C Somayajulu #include "ecore_int.h"
4511e25f0dSDavid C Somayajulu #include "ecore_cxt.h"
4611e25f0dSDavid C Somayajulu #include "ecore_spq.h"
4711e25f0dSDavid C Somayajulu #include "ecore_init_fw_funcs.h"
4811e25f0dSDavid C Somayajulu #include "ecore_sp_commands.h"
4911e25f0dSDavid C Somayajulu #include "ecore_dev_api.h"
5011e25f0dSDavid C Somayajulu #include "ecore_l2_api.h"
5111e25f0dSDavid C Somayajulu #include "ecore_mcp.h"
5211e25f0dSDavid C Somayajulu #include "ecore_hw_defs.h"
5311e25f0dSDavid C Somayajulu #include "mcp_public.h"
5411e25f0dSDavid C Somayajulu #include "ecore_iro.h"
5511e25f0dSDavid C Somayajulu #include "nvm_cfg.h"
5611e25f0dSDavid C Somayajulu #include "ecore_dbg_fw_funcs.h"
57217ec208SDavid C Somayajulu #include "ecore_iov_api.h"
58217ec208SDavid C Somayajulu #include "ecore_vf_api.h"
5911e25f0dSDavid C Somayajulu 
6011e25f0dSDavid C Somayajulu #include "qlnx_ioctl.h"
6111e25f0dSDavid C Somayajulu #include "qlnx_def.h"
6211e25f0dSDavid C Somayajulu #include "qlnx_ver.h"
63217ec208SDavid C Somayajulu 
64217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
65217ec208SDavid C Somayajulu #include "qlnx_rdma.h"
66217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
67217ec208SDavid C Somayajulu 
6899e5ffe1SMark O'Donovan #ifdef CONFIG_ECORE_SRIOV
6999e5ffe1SMark O'Donovan #include <sys/nv.h>
7099e5ffe1SMark O'Donovan #include <sys/iov_schema.h>
7199e5ffe1SMark O'Donovan #include <dev/pci/pci_iov.h>
7299e5ffe1SMark O'Donovan #endif /* #ifdef CONFIG_ECORE_SRIOV */
7399e5ffe1SMark O'Donovan 
7411e25f0dSDavid C Somayajulu #include <sys/smp.h>
7511e25f0dSDavid C Somayajulu 
7611e25f0dSDavid C Somayajulu /*
7711e25f0dSDavid C Somayajulu  * static functions
7811e25f0dSDavid C Somayajulu  */
7911e25f0dSDavid C Somayajulu /*
8011e25f0dSDavid C Somayajulu  * ioctl related functions
8111e25f0dSDavid C Somayajulu  */
8211e25f0dSDavid C Somayajulu static void qlnx_add_sysctls(qlnx_host_t *ha);
8311e25f0dSDavid C Somayajulu 
8411e25f0dSDavid C Somayajulu /*
8511e25f0dSDavid C Somayajulu  * main driver
8611e25f0dSDavid C Somayajulu  */
8711e25f0dSDavid C Somayajulu static void qlnx_release(qlnx_host_t *ha);
8811e25f0dSDavid C Somayajulu static void qlnx_fp_isr(void *arg);
8911e25f0dSDavid C Somayajulu static void qlnx_init_ifnet(device_t dev, qlnx_host_t *ha);
9011e25f0dSDavid C Somayajulu static void qlnx_init(void *arg);
9111e25f0dSDavid C Somayajulu static void qlnx_init_locked(qlnx_host_t *ha);
9211e25f0dSDavid C Somayajulu static int qlnx_set_multi(qlnx_host_t *ha, uint32_t add_multi);
93e3ec564eSKeith Reynolds static int qlnx_set_promisc(qlnx_host_t *ha, int enabled);
94e3ec564eSKeith Reynolds static int qlnx_set_allmulti(qlnx_host_t *ha, int enabled);
95727bfe38SJustin Hibbits static int qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data);
96727bfe38SJustin Hibbits static int qlnx_media_change(if_t ifp);
97727bfe38SJustin Hibbits static void qlnx_media_status(if_t ifp, struct ifmediareq *ifmr);
9811e25f0dSDavid C Somayajulu static void qlnx_stop(qlnx_host_t *ha);
9911e25f0dSDavid C Somayajulu static int qlnx_send(qlnx_host_t *ha, struct qlnx_fastpath *fp,
10011e25f0dSDavid C Somayajulu 		struct mbuf **m_headp);
10111e25f0dSDavid C Somayajulu static int qlnx_get_ifq_snd_maxlen(qlnx_host_t *ha);
10211e25f0dSDavid C Somayajulu static uint32_t qlnx_get_optics(qlnx_host_t *ha,
10311e25f0dSDavid C Somayajulu 			struct qlnx_link_output *if_link);
104727bfe38SJustin Hibbits static int qlnx_transmit(if_t ifp, struct mbuf  *mp);
105727bfe38SJustin Hibbits static int qlnx_transmit_locked(if_t ifp, struct qlnx_fastpath *fp,
10645f13123SDavid C Somayajulu 		struct mbuf *mp);
107727bfe38SJustin Hibbits static void qlnx_qflush(if_t ifp);
10811e25f0dSDavid C Somayajulu 
10911e25f0dSDavid C Somayajulu static int qlnx_alloc_parent_dma_tag(qlnx_host_t *ha);
11011e25f0dSDavid C Somayajulu static void qlnx_free_parent_dma_tag(qlnx_host_t *ha);
11111e25f0dSDavid C Somayajulu static int qlnx_alloc_tx_dma_tag(qlnx_host_t *ha);
11211e25f0dSDavid C Somayajulu static void qlnx_free_tx_dma_tag(qlnx_host_t *ha);
11311e25f0dSDavid C Somayajulu static int qlnx_alloc_rx_dma_tag(qlnx_host_t *ha);
11411e25f0dSDavid C Somayajulu static void qlnx_free_rx_dma_tag(qlnx_host_t *ha);
11511e25f0dSDavid C Somayajulu 
11611e25f0dSDavid C Somayajulu static int qlnx_get_mfw_version(qlnx_host_t *ha, uint32_t *mfw_ver);
11711e25f0dSDavid C Somayajulu static int qlnx_get_flash_size(qlnx_host_t *ha, uint32_t *flash_size);
11811e25f0dSDavid C Somayajulu 
11911e25f0dSDavid C Somayajulu static int qlnx_nic_setup(struct ecore_dev *cdev,
12011e25f0dSDavid C Somayajulu 		struct ecore_pf_params *func_params);
12111e25f0dSDavid C Somayajulu static int qlnx_nic_start(struct ecore_dev *cdev);
12211e25f0dSDavid C Somayajulu static int qlnx_slowpath_start(qlnx_host_t *ha);
12311e25f0dSDavid C Somayajulu static int qlnx_slowpath_stop(qlnx_host_t *ha);
12411e25f0dSDavid C Somayajulu static int qlnx_init_hw(qlnx_host_t *ha);
12511e25f0dSDavid C Somayajulu static void qlnx_set_id(struct ecore_dev *cdev, char name[NAME_SIZE],
12611e25f0dSDavid C Somayajulu 		char ver_str[VER_SIZE]);
12711e25f0dSDavid C Somayajulu static void qlnx_unload(qlnx_host_t *ha);
12811e25f0dSDavid C Somayajulu static int qlnx_load(qlnx_host_t *ha);
12911e25f0dSDavid C Somayajulu static void qlnx_hw_set_multi(qlnx_host_t *ha, uint8_t *mta, uint32_t mcnt,
13011e25f0dSDavid C Somayajulu 		uint32_t add_mac);
13111e25f0dSDavid C Somayajulu static void qlnx_dump_buf8(qlnx_host_t *ha, const char *msg, void *dbuf,
13211e25f0dSDavid C Somayajulu 		uint32_t len);
13311e25f0dSDavid C Somayajulu static int qlnx_alloc_rx_buffer(qlnx_host_t *ha, struct qlnx_rx_queue *rxq);
13411e25f0dSDavid C Somayajulu static void qlnx_reuse_rx_data(struct qlnx_rx_queue *rxq);
13511e25f0dSDavid C Somayajulu static void qlnx_update_rx_prod(struct ecore_hwfn *p_hwfn,
13611e25f0dSDavid C Somayajulu 		struct qlnx_rx_queue *rxq);
13711e25f0dSDavid C Somayajulu static int qlnx_set_rx_accept_filter(qlnx_host_t *ha, uint8_t filter);
13811e25f0dSDavid C Somayajulu static int qlnx_grc_dumpsize(qlnx_host_t *ha, uint32_t *num_dwords,
13911e25f0dSDavid C Somayajulu 		int hwfn_index);
14011e25f0dSDavid C Somayajulu static int qlnx_idle_chk_size(qlnx_host_t *ha, uint32_t *num_dwords,
14111e25f0dSDavid C Somayajulu 		int hwfn_index);
14211e25f0dSDavid C Somayajulu static void qlnx_timer(void *arg);
14311e25f0dSDavid C Somayajulu static int qlnx_alloc_tx_br(qlnx_host_t *ha, struct qlnx_fastpath *fp);
14411e25f0dSDavid C Somayajulu static void qlnx_free_tx_br(qlnx_host_t *ha, struct qlnx_fastpath *fp);
14511e25f0dSDavid C Somayajulu static void qlnx_trigger_dump(qlnx_host_t *ha);
14645f13123SDavid C Somayajulu static uint16_t qlnx_num_tx_compl(qlnx_host_t *ha, struct qlnx_fastpath *fp,
14745f13123SDavid C Somayajulu 			struct qlnx_tx_queue *txq);
14811e25f0dSDavid C Somayajulu static void qlnx_tx_int(qlnx_host_t *ha, struct qlnx_fastpath *fp,
14911e25f0dSDavid C Somayajulu 		struct qlnx_tx_queue *txq);
15011e25f0dSDavid C Somayajulu static int qlnx_rx_int(qlnx_host_t *ha, struct qlnx_fastpath *fp, int budget,
15111e25f0dSDavid C Somayajulu 		int lro_enable);
15211e25f0dSDavid C Somayajulu static void qlnx_fp_taskqueue(void *context, int pending);
15311e25f0dSDavid C Somayajulu static void qlnx_sample_storm_stats(qlnx_host_t *ha);
15411e25f0dSDavid C Somayajulu static int qlnx_alloc_tpa_mbuf(qlnx_host_t *ha, uint16_t rx_buf_size,
15511e25f0dSDavid C Somayajulu 		struct qlnx_agg_info *tpa);
15611e25f0dSDavid C Somayajulu static void qlnx_free_tpa_mbuf(qlnx_host_t *ha, struct qlnx_agg_info *tpa);
15711e25f0dSDavid C Somayajulu 
15811e25f0dSDavid C Somayajulu static uint64_t qlnx_get_counter(if_t ifp, ift_counter cnt);
15911e25f0dSDavid C Somayajulu 
16011e25f0dSDavid C Somayajulu /*
16111e25f0dSDavid C Somayajulu  * Hooks to the Operating Systems
16211e25f0dSDavid C Somayajulu  */
16311e25f0dSDavid C Somayajulu static int qlnx_pci_probe (device_t);
16411e25f0dSDavid C Somayajulu static int qlnx_pci_attach (device_t);
16511e25f0dSDavid C Somayajulu static int qlnx_pci_detach (device_t);
16611e25f0dSDavid C Somayajulu 
167217ec208SDavid C Somayajulu #ifndef QLNX_VF
168217ec208SDavid C Somayajulu 
169217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
170217ec208SDavid C Somayajulu 
171217ec208SDavid C Somayajulu static int qlnx_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params);
172217ec208SDavid C Somayajulu static void qlnx_iov_uninit(device_t dev);
173217ec208SDavid C Somayajulu static int qlnx_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params);
174217ec208SDavid C Somayajulu static void qlnx_initialize_sriov(qlnx_host_t *ha);
175217ec208SDavid C Somayajulu static void qlnx_pf_taskqueue(void *context, int pending);
176217ec208SDavid C Somayajulu static int qlnx_create_pf_taskqueues(qlnx_host_t *ha);
177217ec208SDavid C Somayajulu static void qlnx_destroy_pf_taskqueues(qlnx_host_t *ha);
178217ec208SDavid C Somayajulu static void qlnx_inform_vf_link_state(struct ecore_hwfn *p_hwfn, qlnx_host_t *ha);
179217ec208SDavid C Somayajulu 
180217ec208SDavid C Somayajulu #endif /* #ifdef CONFIG_ECORE_SRIOV */
181217ec208SDavid C Somayajulu 
18211e25f0dSDavid C Somayajulu static device_method_t qlnx_pci_methods[] = {
18311e25f0dSDavid C Somayajulu 	/* Device interface */
18411e25f0dSDavid C Somayajulu 	DEVMETHOD(device_probe, qlnx_pci_probe),
18511e25f0dSDavid C Somayajulu 	DEVMETHOD(device_attach, qlnx_pci_attach),
18611e25f0dSDavid C Somayajulu 	DEVMETHOD(device_detach, qlnx_pci_detach),
187217ec208SDavid C Somayajulu 
188217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
189217ec208SDavid C Somayajulu 	DEVMETHOD(pci_iov_init, qlnx_iov_init),
190217ec208SDavid C Somayajulu 	DEVMETHOD(pci_iov_uninit, qlnx_iov_uninit),
191217ec208SDavid C Somayajulu 	DEVMETHOD(pci_iov_add_vf, qlnx_iov_add_vf),
192217ec208SDavid C Somayajulu #endif /* #ifdef CONFIG_ECORE_SRIOV */
19311e25f0dSDavid C Somayajulu 	{ 0, 0 }
19411e25f0dSDavid C Somayajulu };
19511e25f0dSDavid C Somayajulu 
19611e25f0dSDavid C Somayajulu static driver_t qlnx_pci_driver = {
19711e25f0dSDavid C Somayajulu 	"ql", qlnx_pci_methods, sizeof (qlnx_host_t),
19811e25f0dSDavid C Somayajulu };
19911e25f0dSDavid C Somayajulu 
20011e25f0dSDavid C Somayajulu MODULE_VERSION(if_qlnxe,1);
2012f87208eSJohn Baldwin DRIVER_MODULE(if_qlnxe, pci, qlnx_pci_driver, 0, 0);
20211e25f0dSDavid C Somayajulu 
20311e25f0dSDavid C Somayajulu MODULE_DEPEND(if_qlnxe, pci, 1, 1, 1);
20411e25f0dSDavid C Somayajulu MODULE_DEPEND(if_qlnxe, ether, 1, 1, 1);
20511e25f0dSDavid C Somayajulu 
206217ec208SDavid C Somayajulu #else
207217ec208SDavid C Somayajulu 
208217ec208SDavid C Somayajulu static device_method_t qlnxv_pci_methods[] = {
209217ec208SDavid C Somayajulu 	/* Device interface */
210217ec208SDavid C Somayajulu 	DEVMETHOD(device_probe, qlnx_pci_probe),
211217ec208SDavid C Somayajulu 	DEVMETHOD(device_attach, qlnx_pci_attach),
212217ec208SDavid C Somayajulu 	DEVMETHOD(device_detach, qlnx_pci_detach),
213217ec208SDavid C Somayajulu 	{ 0, 0 }
214217ec208SDavid C Somayajulu };
215217ec208SDavid C Somayajulu 
216217ec208SDavid C Somayajulu static driver_t qlnxv_pci_driver = {
217217ec208SDavid C Somayajulu 	"ql", qlnxv_pci_methods, sizeof (qlnx_host_t),
218217ec208SDavid C Somayajulu };
219217ec208SDavid C Somayajulu 
220217ec208SDavid C Somayajulu MODULE_VERSION(if_qlnxev,1);
2212f87208eSJohn Baldwin DRIVER_MODULE(if_qlnxev, pci, qlnxv_pci_driver, 0, 0);
222217ec208SDavid C Somayajulu 
223217ec208SDavid C Somayajulu MODULE_DEPEND(if_qlnxev, pci, 1, 1, 1);
224217ec208SDavid C Somayajulu MODULE_DEPEND(if_qlnxev, ether, 1, 1, 1);
225217ec208SDavid C Somayajulu 
226217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_VF */
227217ec208SDavid C Somayajulu 
22811e25f0dSDavid C Somayajulu MALLOC_DEFINE(M_QLNXBUF, "qlnxbuf", "Buffers for qlnx driver");
22911e25f0dSDavid C Somayajulu 
230d3588766SMark Johnston char qlnx_ver_str[VER_SIZE];
231d3588766SMark Johnston char qlnx_name_str[NAME_SIZE];
23211e25f0dSDavid C Somayajulu 
23311e25f0dSDavid C Somayajulu /*
23411e25f0dSDavid C Somayajulu  * Some PCI Configuration Space Related Defines
23511e25f0dSDavid C Somayajulu  */
23611e25f0dSDavid C Somayajulu 
23711e25f0dSDavid C Somayajulu #ifndef PCI_VENDOR_QLOGIC
23811e25f0dSDavid C Somayajulu #define PCI_VENDOR_QLOGIC		0x1077
23911e25f0dSDavid C Somayajulu #endif
24011e25f0dSDavid C Somayajulu 
24111e25f0dSDavid C Somayajulu /* 40G Adapter QLE45xxx*/
24211e25f0dSDavid C Somayajulu #ifndef QLOGIC_PCI_DEVICE_ID_1634
24311e25f0dSDavid C Somayajulu #define QLOGIC_PCI_DEVICE_ID_1634	0x1634
24411e25f0dSDavid C Somayajulu #endif
24511e25f0dSDavid C Somayajulu 
24611e25f0dSDavid C Somayajulu /* 100G Adapter QLE45xxx*/
24711e25f0dSDavid C Somayajulu #ifndef QLOGIC_PCI_DEVICE_ID_1644
24811e25f0dSDavid C Somayajulu #define QLOGIC_PCI_DEVICE_ID_1644	0x1644
24911e25f0dSDavid C Somayajulu #endif
25011e25f0dSDavid C Somayajulu 
25111e25f0dSDavid C Somayajulu /* 25G Adapter QLE45xxx*/
25211e25f0dSDavid C Somayajulu #ifndef QLOGIC_PCI_DEVICE_ID_1656
25311e25f0dSDavid C Somayajulu #define QLOGIC_PCI_DEVICE_ID_1656	0x1656
25411e25f0dSDavid C Somayajulu #endif
25511e25f0dSDavid C Somayajulu 
25611e25f0dSDavid C Somayajulu /* 50G Adapter QLE45xxx*/
25711e25f0dSDavid C Somayajulu #ifndef QLOGIC_PCI_DEVICE_ID_1654
25811e25f0dSDavid C Somayajulu #define QLOGIC_PCI_DEVICE_ID_1654	0x1654
25911e25f0dSDavid C Somayajulu #endif
26011e25f0dSDavid C Somayajulu 
2619efd0ba7SDavid C Somayajulu /* 10G/25G/40G Adapter QLE41xxx*/
2629efd0ba7SDavid C Somayajulu #ifndef QLOGIC_PCI_DEVICE_ID_8070
2639efd0ba7SDavid C Somayajulu #define QLOGIC_PCI_DEVICE_ID_8070	0x8070
2649efd0ba7SDavid C Somayajulu #endif
2659efd0ba7SDavid C Somayajulu 
266217ec208SDavid C Somayajulu /* SRIOV Device (All Speeds) Adapter QLE41xxx*/
267217ec208SDavid C Somayajulu #ifndef QLOGIC_PCI_DEVICE_ID_8090
268217ec208SDavid C Somayajulu #define QLOGIC_PCI_DEVICE_ID_8090	0x8090
269217ec208SDavid C Somayajulu #endif
270217ec208SDavid C Somayajulu 
2717029da5cSPawel Biernacki SYSCTL_NODE(_hw, OID_AUTO, qlnxe, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
2727029da5cSPawel Biernacki     "qlnxe driver parameters");
273217ec208SDavid C Somayajulu 
27445f13123SDavid C Somayajulu /* Number of Queues: 0 (Auto) or 1 to 32 (fixed queue number) */
27545f13123SDavid C Somayajulu static int qlnxe_queue_count = QLNX_DEFAULT_RSS;
276217ec208SDavid C Somayajulu 
27745f13123SDavid C Somayajulu SYSCTL_INT(_hw_qlnxe, OID_AUTO, queue_count, CTLFLAG_RDTUN,
27845f13123SDavid C Somayajulu 		&qlnxe_queue_count, 0, "Multi-Queue queue count");
27945f13123SDavid C Somayajulu 
280217ec208SDavid C Somayajulu /*
281217ec208SDavid C Somayajulu  * Note on RDMA personality setting
282217ec208SDavid C Somayajulu  *
283217ec208SDavid C Somayajulu  * Read the personality configured in NVRAM
284217ec208SDavid C Somayajulu  * If the personality is ETH_ONLY, ETH_IWARP or ETH_ROCE and
285217ec208SDavid C Somayajulu  * the configured personality in sysctl is QLNX_PERSONALITY_DEFAULT
286217ec208SDavid C Somayajulu  * use the personality in NVRAM.
287217ec208SDavid C Somayajulu 
288217ec208SDavid C Somayajulu  * Otherwise use t the personality configured in sysctl.
289217ec208SDavid C Somayajulu  *
290217ec208SDavid C Somayajulu  */
291217ec208SDavid C Somayajulu #define QLNX_PERSONALITY_DEFAULT	0x0  /* use personality in NVRAM */
292217ec208SDavid C Somayajulu #define QLNX_PERSONALITY_ETH_ONLY	0x1  /* Override with ETH_ONLY */
293217ec208SDavid C Somayajulu #define QLNX_PERSONALITY_ETH_IWARP	0x2  /* Override with ETH_IWARP */
294217ec208SDavid C Somayajulu #define QLNX_PERSONALITY_ETH_ROCE	0x3  /* Override with ETH_ROCE */
295217ec208SDavid C Somayajulu #define QLNX_PERSONALITY_BITS_PER_FUNC	4
296217ec208SDavid C Somayajulu #define QLNX_PERSONALIY_MASK		0xF
297217ec208SDavid C Somayajulu 
298217ec208SDavid C Somayajulu /* RDMA configuration; 64bit field allows setting for 16 physical functions*/
299217ec208SDavid C Somayajulu static uint64_t qlnxe_rdma_configuration = 0x22222222;
300217ec208SDavid C Somayajulu 
301217ec208SDavid C Somayajulu SYSCTL_U64(_hw_qlnxe, OID_AUTO, rdma_configuration, CTLFLAG_RDTUN,
302217ec208SDavid C Somayajulu                 &qlnxe_rdma_configuration, 0, "RDMA Configuration");
303217ec208SDavid C Somayajulu 
304217ec208SDavid C Somayajulu int
qlnx_vf_device(qlnx_host_t * ha)305217ec208SDavid C Somayajulu qlnx_vf_device(qlnx_host_t *ha)
30611e25f0dSDavid C Somayajulu {
30711e25f0dSDavid C Somayajulu         uint16_t	device_id;
30811e25f0dSDavid C Somayajulu 
309217ec208SDavid C Somayajulu         device_id = ha->device_id;
31011e25f0dSDavid C Somayajulu 
311217ec208SDavid C Somayajulu         if (device_id == QLOGIC_PCI_DEVICE_ID_8090)
312217ec208SDavid C Somayajulu                 return 0;
313217ec208SDavid C Somayajulu 
314217ec208SDavid C Somayajulu         return -1;
315217ec208SDavid C Somayajulu }
316217ec208SDavid C Somayajulu 
317217ec208SDavid C Somayajulu static int
qlnx_valid_device(qlnx_host_t * ha)318217ec208SDavid C Somayajulu qlnx_valid_device(qlnx_host_t *ha)
319217ec208SDavid C Somayajulu {
320217ec208SDavid C Somayajulu         uint16_t device_id;
321217ec208SDavid C Somayajulu 
322217ec208SDavid C Somayajulu         device_id = ha->device_id;
323217ec208SDavid C Somayajulu 
324217ec208SDavid C Somayajulu #ifndef QLNX_VF
32511e25f0dSDavid C Somayajulu         if ((device_id == QLOGIC_PCI_DEVICE_ID_1634) ||
32611e25f0dSDavid C Somayajulu                 (device_id == QLOGIC_PCI_DEVICE_ID_1644) ||
32711e25f0dSDavid C Somayajulu                 (device_id == QLOGIC_PCI_DEVICE_ID_1656) ||
3289efd0ba7SDavid C Somayajulu                 (device_id == QLOGIC_PCI_DEVICE_ID_1654) ||
3299efd0ba7SDavid C Somayajulu                 (device_id == QLOGIC_PCI_DEVICE_ID_8070))
33011e25f0dSDavid C Somayajulu                 return 0;
331217ec208SDavid C Somayajulu #else
332217ec208SDavid C Somayajulu         if (device_id == QLOGIC_PCI_DEVICE_ID_8090)
333217ec208SDavid C Somayajulu 		return 0;
33411e25f0dSDavid C Somayajulu 
335217ec208SDavid C Somayajulu #endif /* #ifndef QLNX_VF */
33611e25f0dSDavid C Somayajulu         return -1;
33711e25f0dSDavid C Somayajulu }
33811e25f0dSDavid C Somayajulu 
339217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
340217ec208SDavid C Somayajulu static int
qlnx_rdma_supported(struct qlnx_host * ha)341217ec208SDavid C Somayajulu qlnx_rdma_supported(struct qlnx_host *ha)
342217ec208SDavid C Somayajulu {
343217ec208SDavid C Somayajulu 	uint16_t device_id;
344217ec208SDavid C Somayajulu 
345217ec208SDavid C Somayajulu 	device_id = pci_get_device(ha->pci_dev);
346217ec208SDavid C Somayajulu 
347217ec208SDavid C Somayajulu 	if ((device_id == QLOGIC_PCI_DEVICE_ID_1634) ||
348217ec208SDavid C Somayajulu 		(device_id == QLOGIC_PCI_DEVICE_ID_1656) ||
349217ec208SDavid C Somayajulu 		(device_id == QLOGIC_PCI_DEVICE_ID_1654) ||
350217ec208SDavid C Somayajulu 		(device_id == QLOGIC_PCI_DEVICE_ID_8070))
351217ec208SDavid C Somayajulu 		return (0);
352217ec208SDavid C Somayajulu 
353217ec208SDavid C Somayajulu 	return (-1);
354217ec208SDavid C Somayajulu }
355217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
356217ec208SDavid C Somayajulu 
35711e25f0dSDavid C Somayajulu /*
35811e25f0dSDavid C Somayajulu  * Name:	qlnx_pci_probe
35911e25f0dSDavid C Somayajulu  * Function:	Validate the PCI device to be a QLA80XX device
36011e25f0dSDavid C Somayajulu  */
36111e25f0dSDavid C Somayajulu static int
qlnx_pci_probe(device_t dev)36211e25f0dSDavid C Somayajulu qlnx_pci_probe(device_t dev)
36311e25f0dSDavid C Somayajulu {
36411e25f0dSDavid C Somayajulu 	snprintf(qlnx_ver_str, sizeof(qlnx_ver_str), "v%d.%d.%d",
36511e25f0dSDavid C Somayajulu 		QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR, QLNX_VERSION_BUILD);
36611e25f0dSDavid C Somayajulu 	snprintf(qlnx_name_str, sizeof(qlnx_name_str), "qlnx");
36711e25f0dSDavid C Somayajulu 
36811e25f0dSDavid C Somayajulu 	if (pci_get_vendor(dev) != PCI_VENDOR_QLOGIC) {
36911e25f0dSDavid C Somayajulu                 return (ENXIO);
37011e25f0dSDavid C Somayajulu 	}
37111e25f0dSDavid C Somayajulu 
37211e25f0dSDavid C Somayajulu         switch (pci_get_device(dev)) {
373217ec208SDavid C Somayajulu #ifndef QLNX_VF
374217ec208SDavid C Somayajulu 
37511e25f0dSDavid C Somayajulu         case QLOGIC_PCI_DEVICE_ID_1644:
376801b12baSMark Johnston 		device_set_descf(dev, "%s v%d.%d.%d",
37711e25f0dSDavid C Somayajulu 			"Qlogic 100GbE PCI CNA Adapter-Ethernet Function",
37811e25f0dSDavid C Somayajulu 			QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR,
37911e25f0dSDavid C Somayajulu 			QLNX_VERSION_BUILD);
38011e25f0dSDavid C Somayajulu                 break;
38111e25f0dSDavid C Somayajulu 
38211e25f0dSDavid C Somayajulu         case QLOGIC_PCI_DEVICE_ID_1634:
383801b12baSMark Johnston 		device_set_descf(dev, "%s v%d.%d.%d",
38411e25f0dSDavid C Somayajulu 			"Qlogic 40GbE PCI CNA Adapter-Ethernet Function",
38511e25f0dSDavid C Somayajulu 			QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR,
38611e25f0dSDavid C Somayajulu 			QLNX_VERSION_BUILD);
38711e25f0dSDavid C Somayajulu                 break;
38811e25f0dSDavid C Somayajulu 
38911e25f0dSDavid C Somayajulu         case QLOGIC_PCI_DEVICE_ID_1656:
390801b12baSMark Johnston 		device_set_descf(dev, "%s v%d.%d.%d",
39111e25f0dSDavid C Somayajulu 			"Qlogic 25GbE PCI CNA Adapter-Ethernet Function",
39211e25f0dSDavid C Somayajulu 			QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR,
39311e25f0dSDavid C Somayajulu 			QLNX_VERSION_BUILD);
39411e25f0dSDavid C Somayajulu                 break;
39511e25f0dSDavid C Somayajulu 
39611e25f0dSDavid C Somayajulu         case QLOGIC_PCI_DEVICE_ID_1654:
397801b12baSMark Johnston 		device_set_descf(dev, "%s v%d.%d.%d",
39811e25f0dSDavid C Somayajulu 			"Qlogic 50GbE PCI CNA Adapter-Ethernet Function",
39911e25f0dSDavid C Somayajulu 			QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR,
40011e25f0dSDavid C Somayajulu 			QLNX_VERSION_BUILD);
40111e25f0dSDavid C Somayajulu                 break;
40211e25f0dSDavid C Somayajulu 
4039efd0ba7SDavid C Somayajulu 	case QLOGIC_PCI_DEVICE_ID_8070:
404801b12baSMark Johnston 		device_set_descf(dev, "%s v%d.%d.%d",
4059efd0ba7SDavid C Somayajulu 			"Qlogic 10GbE/25GbE/40GbE PCI CNA (AH)"
4069efd0ba7SDavid C Somayajulu 			" Adapter-Ethernet Function",
4079efd0ba7SDavid C Somayajulu 			QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR,
4089efd0ba7SDavid C Somayajulu 			QLNX_VERSION_BUILD);
4099efd0ba7SDavid C Somayajulu 		break;
4109efd0ba7SDavid C Somayajulu 
411217ec208SDavid C Somayajulu #else
412217ec208SDavid C Somayajulu 	case QLOGIC_PCI_DEVICE_ID_8090:
413801b12baSMark Johnston 		device_set_descf(dev, "%s v%d.%d.%d",
414217ec208SDavid C Somayajulu 			"Qlogic SRIOV PCI CNA (AH) "
415217ec208SDavid C Somayajulu 			"Adapter-Ethernet Function",
416217ec208SDavid C Somayajulu 			QLNX_VERSION_MAJOR, QLNX_VERSION_MINOR,
417217ec208SDavid C Somayajulu 			QLNX_VERSION_BUILD);
418217ec208SDavid C Somayajulu 		break;
419217ec208SDavid C Somayajulu 
420217ec208SDavid C Somayajulu #endif /* #ifndef QLNX_VF */
421217ec208SDavid C Somayajulu 
42211e25f0dSDavid C Somayajulu         default:
42311e25f0dSDavid C Somayajulu                 return (ENXIO);
42411e25f0dSDavid C Somayajulu         }
42511e25f0dSDavid C Somayajulu 
426217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
427217ec208SDavid C Somayajulu 	qlnx_rdma_init();
428217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
429217ec208SDavid C Somayajulu 
43011e25f0dSDavid C Somayajulu         return (BUS_PROBE_DEFAULT);
43111e25f0dSDavid C Somayajulu }
43211e25f0dSDavid C Somayajulu 
43345f13123SDavid C Somayajulu static uint16_t
qlnx_num_tx_compl(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_tx_queue * txq)43445f13123SDavid C Somayajulu qlnx_num_tx_compl(qlnx_host_t *ha, struct qlnx_fastpath *fp,
43545f13123SDavid C Somayajulu 	struct qlnx_tx_queue *txq)
43645f13123SDavid C Somayajulu {
43745f13123SDavid C Somayajulu 	u16 hw_bd_cons;
43845f13123SDavid C Somayajulu 	u16 ecore_cons_idx;
43945f13123SDavid C Somayajulu 
44045f13123SDavid C Somayajulu 	hw_bd_cons = le16toh(*txq->hw_cons_ptr);
44145f13123SDavid C Somayajulu 
44245f13123SDavid C Somayajulu 	ecore_cons_idx = ecore_chain_get_cons_idx(&txq->tx_pbl);
443406ff3d5SMark O'Donovan 
444406ff3d5SMark O'Donovan 	return (hw_bd_cons - ecore_cons_idx);
44545f13123SDavid C Somayajulu }
44645f13123SDavid C Somayajulu 
44711e25f0dSDavid C Somayajulu static void
qlnx_sp_intr(void * arg)44811e25f0dSDavid C Somayajulu qlnx_sp_intr(void *arg)
44911e25f0dSDavid C Somayajulu {
45011e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
45111e25f0dSDavid C Somayajulu 	qlnx_host_t		*ha;
45211e25f0dSDavid C Somayajulu 	int			i;
45311e25f0dSDavid C Somayajulu 
45411e25f0dSDavid C Somayajulu 	p_hwfn = arg;
45511e25f0dSDavid C Somayajulu 
45611e25f0dSDavid C Somayajulu 	if (p_hwfn == NULL) {
45711e25f0dSDavid C Somayajulu 		printf("%s: spurious slowpath intr\n", __func__);
45811e25f0dSDavid C Somayajulu 		return;
45911e25f0dSDavid C Somayajulu 	}
46011e25f0dSDavid C Somayajulu 
46111e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)p_hwfn->p_dev;
46211e25f0dSDavid C Somayajulu 
4637a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
46411e25f0dSDavid C Somayajulu 
46511e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
46611e25f0dSDavid C Somayajulu 		if (&ha->cdev.hwfns[i] == p_hwfn) {
46711e25f0dSDavid C Somayajulu 			taskqueue_enqueue(ha->sp_taskqueue[i], &ha->sp_task[i]);
46811e25f0dSDavid C Somayajulu 			break;
46911e25f0dSDavid C Somayajulu 		}
47011e25f0dSDavid C Somayajulu 	}
4717a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
47211e25f0dSDavid C Somayajulu 
47311e25f0dSDavid C Somayajulu 	return;
47411e25f0dSDavid C Somayajulu }
47511e25f0dSDavid C Somayajulu 
47611e25f0dSDavid C Somayajulu static void
qlnx_sp_taskqueue(void * context,int pending)47711e25f0dSDavid C Somayajulu qlnx_sp_taskqueue(void *context, int pending)
47811e25f0dSDavid C Somayajulu {
47911e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
48011e25f0dSDavid C Somayajulu 
48111e25f0dSDavid C Somayajulu 	p_hwfn = context;
48211e25f0dSDavid C Somayajulu 
48311e25f0dSDavid C Somayajulu 	if (p_hwfn != NULL) {
48411e25f0dSDavid C Somayajulu 		qlnx_sp_isr(p_hwfn);
48511e25f0dSDavid C Somayajulu 	}
48611e25f0dSDavid C Somayajulu 	return;
48711e25f0dSDavid C Somayajulu }
48811e25f0dSDavid C Somayajulu 
48911e25f0dSDavid C Somayajulu static int
qlnx_create_sp_taskqueues(qlnx_host_t * ha)49011e25f0dSDavid C Somayajulu qlnx_create_sp_taskqueues(qlnx_host_t *ha)
49111e25f0dSDavid C Somayajulu {
49211e25f0dSDavid C Somayajulu 	int	i;
49311e25f0dSDavid C Somayajulu 	uint8_t	tq_name[32];
49411e25f0dSDavid C Somayajulu 
49511e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
49611e25f0dSDavid C Somayajulu                 struct ecore_hwfn *p_hwfn = &ha->cdev.hwfns[i];
49711e25f0dSDavid C Somayajulu 
49811e25f0dSDavid C Somayajulu 		bzero(tq_name, sizeof (tq_name));
49911e25f0dSDavid C Somayajulu 		snprintf(tq_name, sizeof (tq_name), "ql_sp_tq_%d", i);
50011e25f0dSDavid C Somayajulu 
50111e25f0dSDavid C Somayajulu 		TASK_INIT(&ha->sp_task[i], 0, qlnx_sp_taskqueue, p_hwfn);
50211e25f0dSDavid C Somayajulu 
503217ec208SDavid C Somayajulu 		ha->sp_taskqueue[i] = taskqueue_create(tq_name, M_NOWAIT,
50411e25f0dSDavid C Somayajulu 			 taskqueue_thread_enqueue, &ha->sp_taskqueue[i]);
50511e25f0dSDavid C Somayajulu 
50611e25f0dSDavid C Somayajulu 		if (ha->sp_taskqueue[i] == NULL)
50711e25f0dSDavid C Somayajulu 			return (-1);
50811e25f0dSDavid C Somayajulu 
50911e25f0dSDavid C Somayajulu 		taskqueue_start_threads(&ha->sp_taskqueue[i], 1, PI_NET, "%s",
51011e25f0dSDavid C Somayajulu 			tq_name);
51111e25f0dSDavid C Somayajulu 
5127a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "%p\n", ha->sp_taskqueue[i]);
51311e25f0dSDavid C Somayajulu 	}
51411e25f0dSDavid C Somayajulu 
51511e25f0dSDavid C Somayajulu 	return (0);
51611e25f0dSDavid C Somayajulu }
51711e25f0dSDavid C Somayajulu 
51811e25f0dSDavid C Somayajulu static void
qlnx_destroy_sp_taskqueues(qlnx_host_t * ha)51911e25f0dSDavid C Somayajulu qlnx_destroy_sp_taskqueues(qlnx_host_t *ha)
52011e25f0dSDavid C Somayajulu {
52111e25f0dSDavid C Somayajulu 	int	i;
52211e25f0dSDavid C Somayajulu 
52311e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
52411e25f0dSDavid C Somayajulu 		if (ha->sp_taskqueue[i] != NULL) {
52511e25f0dSDavid C Somayajulu 			taskqueue_drain(ha->sp_taskqueue[i], &ha->sp_task[i]);
52611e25f0dSDavid C Somayajulu 			taskqueue_free(ha->sp_taskqueue[i]);
52711e25f0dSDavid C Somayajulu 		}
52811e25f0dSDavid C Somayajulu 	}
52911e25f0dSDavid C Somayajulu 	return;
53011e25f0dSDavid C Somayajulu }
53111e25f0dSDavid C Somayajulu 
53211e25f0dSDavid C Somayajulu static void
qlnx_fp_taskqueue(void * context,int pending)53311e25f0dSDavid C Somayajulu qlnx_fp_taskqueue(void *context, int pending)
53411e25f0dSDavid C Somayajulu {
53511e25f0dSDavid C Somayajulu         struct qlnx_fastpath	*fp;
53611e25f0dSDavid C Somayajulu         qlnx_host_t		*ha;
537727bfe38SJustin Hibbits         if_t			ifp;
538b284b46dSDavid C Somayajulu 
53911e25f0dSDavid C Somayajulu         fp = context;
54011e25f0dSDavid C Somayajulu 
54111e25f0dSDavid C Somayajulu         if (fp == NULL)
54211e25f0dSDavid C Somayajulu                 return;
54311e25f0dSDavid C Somayajulu 
54445f13123SDavid C Somayajulu 	ha = (qlnx_host_t *)fp->edev;
54545f13123SDavid C Somayajulu 
54645f13123SDavid C Somayajulu 	ifp = ha->ifp;
54745f13123SDavid C Somayajulu 
548727bfe38SJustin Hibbits         if(if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
54945f13123SDavid C Somayajulu                 if (!drbr_empty(ifp, fp->tx_br)) {
55045f13123SDavid C Somayajulu                         if(mtx_trylock(&fp->tx_mtx)) {
55145f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
55245f13123SDavid C Somayajulu                                 tx_pkts = fp->tx_pkts_transmitted;
55345f13123SDavid C Somayajulu                                 tx_compl = fp->tx_pkts_completed;
55445f13123SDavid C Somayajulu #endif
55545f13123SDavid C Somayajulu 
55645f13123SDavid C Somayajulu                                 qlnx_transmit_locked(ifp, fp, NULL);
55745f13123SDavid C Somayajulu 
55845f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
55945f13123SDavid C Somayajulu                                 fp->tx_pkts_trans_fp +=
56045f13123SDavid C Somayajulu 					(fp->tx_pkts_transmitted - tx_pkts);
56145f13123SDavid C Somayajulu                                 fp->tx_pkts_compl_fp +=
56245f13123SDavid C Somayajulu 					(fp->tx_pkts_completed - tx_compl);
56345f13123SDavid C Somayajulu #endif
56411e25f0dSDavid C Somayajulu                                 mtx_unlock(&fp->tx_mtx);
56511e25f0dSDavid C Somayajulu                         }
56611e25f0dSDavid C Somayajulu                 }
56745f13123SDavid C Somayajulu         }
568b284b46dSDavid C Somayajulu 
56945f13123SDavid C Somayajulu         QL_DPRINT2(ha, "exit \n");
57011e25f0dSDavid C Somayajulu         return;
57111e25f0dSDavid C Somayajulu }
57211e25f0dSDavid C Somayajulu 
57311e25f0dSDavid C Somayajulu static int
qlnx_create_fp_taskqueues(qlnx_host_t * ha)57411e25f0dSDavid C Somayajulu qlnx_create_fp_taskqueues(qlnx_host_t *ha)
57511e25f0dSDavid C Somayajulu {
57611e25f0dSDavid C Somayajulu 	int	i;
57711e25f0dSDavid C Somayajulu 	uint8_t	tq_name[32];
57811e25f0dSDavid C Somayajulu 	struct qlnx_fastpath *fp;
57911e25f0dSDavid C Somayajulu 
58011e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
58111e25f0dSDavid C Somayajulu                 fp = &ha->fp_array[i];
58211e25f0dSDavid C Somayajulu 
58311e25f0dSDavid C Somayajulu 		bzero(tq_name, sizeof (tq_name));
58411e25f0dSDavid C Somayajulu 		snprintf(tq_name, sizeof (tq_name), "ql_fp_tq_%d", i);
58511e25f0dSDavid C Somayajulu 
58611e25f0dSDavid C Somayajulu 		TASK_INIT(&fp->fp_task, 0, qlnx_fp_taskqueue, fp);
58711e25f0dSDavid C Somayajulu 
588217ec208SDavid C Somayajulu 		fp->fp_taskqueue = taskqueue_create(tq_name, M_NOWAIT,
58911e25f0dSDavid C Somayajulu 					taskqueue_thread_enqueue,
59011e25f0dSDavid C Somayajulu 					&fp->fp_taskqueue);
59111e25f0dSDavid C Somayajulu 
59211e25f0dSDavid C Somayajulu 		if (fp->fp_taskqueue == NULL)
59311e25f0dSDavid C Somayajulu 			return (-1);
59411e25f0dSDavid C Somayajulu 
59511e25f0dSDavid C Somayajulu 		taskqueue_start_threads(&fp->fp_taskqueue, 1, PI_NET, "%s",
59611e25f0dSDavid C Somayajulu 			tq_name);
59711e25f0dSDavid C Somayajulu 
5987a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "%p\n",fp->fp_taskqueue);
59911e25f0dSDavid C Somayajulu 	}
60011e25f0dSDavid C Somayajulu 
60111e25f0dSDavid C Somayajulu 	return (0);
60211e25f0dSDavid C Somayajulu }
60311e25f0dSDavid C Somayajulu 
60411e25f0dSDavid C Somayajulu static void
qlnx_destroy_fp_taskqueues(qlnx_host_t * ha)60511e25f0dSDavid C Somayajulu qlnx_destroy_fp_taskqueues(qlnx_host_t *ha)
60611e25f0dSDavid C Somayajulu {
60711e25f0dSDavid C Somayajulu 	int			i;
60811e25f0dSDavid C Somayajulu 	struct qlnx_fastpath	*fp;
60911e25f0dSDavid C Somayajulu 
61011e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
61111e25f0dSDavid C Somayajulu                 fp = &ha->fp_array[i];
61211e25f0dSDavid C Somayajulu 
61311e25f0dSDavid C Somayajulu 		if (fp->fp_taskqueue != NULL) {
61411e25f0dSDavid C Somayajulu 			taskqueue_drain(fp->fp_taskqueue, &fp->fp_task);
61511e25f0dSDavid C Somayajulu 			taskqueue_free(fp->fp_taskqueue);
61611e25f0dSDavid C Somayajulu 			fp->fp_taskqueue = NULL;
61711e25f0dSDavid C Somayajulu 		}
61811e25f0dSDavid C Somayajulu 	}
61911e25f0dSDavid C Somayajulu 	return;
62011e25f0dSDavid C Somayajulu }
62111e25f0dSDavid C Somayajulu 
62211e25f0dSDavid C Somayajulu static void
qlnx_drain_fp_taskqueues(qlnx_host_t * ha)62311e25f0dSDavid C Somayajulu qlnx_drain_fp_taskqueues(qlnx_host_t *ha)
62411e25f0dSDavid C Somayajulu {
62511e25f0dSDavid C Somayajulu 	int			i;
62611e25f0dSDavid C Somayajulu 	struct qlnx_fastpath	*fp;
62711e25f0dSDavid C Somayajulu 
62811e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
62911e25f0dSDavid C Somayajulu                 fp = &ha->fp_array[i];
63011e25f0dSDavid C Somayajulu 
63111e25f0dSDavid C Somayajulu 		if (fp->fp_taskqueue != NULL) {
63277388ed2SDavid C Somayajulu 			QLNX_UNLOCK(ha);
63311e25f0dSDavid C Somayajulu 			taskqueue_drain(fp->fp_taskqueue, &fp->fp_task);
63477388ed2SDavid C Somayajulu 			QLNX_LOCK(ha);
63511e25f0dSDavid C Somayajulu 		}
63611e25f0dSDavid C Somayajulu 	}
63711e25f0dSDavid C Somayajulu 	return;
63811e25f0dSDavid C Somayajulu }
63911e25f0dSDavid C Somayajulu 
64045f13123SDavid C Somayajulu static void
qlnx_get_params(qlnx_host_t * ha)64145f13123SDavid C Somayajulu qlnx_get_params(qlnx_host_t *ha)
64245f13123SDavid C Somayajulu {
64345f13123SDavid C Somayajulu 	if ((qlnxe_queue_count < 0) || (qlnxe_queue_count > QLNX_MAX_RSS)) {
64445f13123SDavid C Somayajulu 		device_printf(ha->pci_dev, "invalid queue_count value (%d)\n",
64545f13123SDavid C Somayajulu 			qlnxe_queue_count);
64645f13123SDavid C Somayajulu 		qlnxe_queue_count = 0;
64745f13123SDavid C Somayajulu 	}
64845f13123SDavid C Somayajulu 	return;
64945f13123SDavid C Somayajulu }
65045f13123SDavid C Somayajulu 
651217ec208SDavid C Somayajulu static void
qlnx_error_recovery_taskqueue(void * context,int pending)652217ec208SDavid C Somayajulu qlnx_error_recovery_taskqueue(void *context, int pending)
653217ec208SDavid C Somayajulu {
654217ec208SDavid C Somayajulu         qlnx_host_t *ha;
655217ec208SDavid C Somayajulu 
656217ec208SDavid C Somayajulu         ha = context;
657217ec208SDavid C Somayajulu 
658217ec208SDavid C Somayajulu         QL_DPRINT2(ha, "enter\n");
659217ec208SDavid C Somayajulu 
660217ec208SDavid C Somayajulu         QLNX_LOCK(ha);
661217ec208SDavid C Somayajulu         qlnx_stop(ha);
662217ec208SDavid C Somayajulu         QLNX_UNLOCK(ha);
663217ec208SDavid C Somayajulu 
664217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
665217ec208SDavid C Somayajulu 	qlnx_rdma_dev_remove(ha);
666217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
667217ec208SDavid C Somayajulu 
668217ec208SDavid C Somayajulu         qlnx_slowpath_stop(ha);
669217ec208SDavid C Somayajulu         qlnx_slowpath_start(ha);
670217ec208SDavid C Somayajulu 
671217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
672217ec208SDavid C Somayajulu 	qlnx_rdma_dev_add(ha);
673217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
674217ec208SDavid C Somayajulu 
675217ec208SDavid C Somayajulu         qlnx_init(ha);
676217ec208SDavid C Somayajulu 
677217ec208SDavid C Somayajulu         callout_reset(&ha->qlnx_callout, hz, qlnx_timer, ha);
678217ec208SDavid C Somayajulu 
679217ec208SDavid C Somayajulu         QL_DPRINT2(ha, "exit\n");
680217ec208SDavid C Somayajulu 
681217ec208SDavid C Somayajulu         return;
682217ec208SDavid C Somayajulu }
683217ec208SDavid C Somayajulu 
684217ec208SDavid C Somayajulu static int
qlnx_create_error_recovery_taskqueue(qlnx_host_t * ha)685217ec208SDavid C Somayajulu qlnx_create_error_recovery_taskqueue(qlnx_host_t *ha)
686217ec208SDavid C Somayajulu {
687217ec208SDavid C Somayajulu         uint8_t tq_name[32];
688217ec208SDavid C Somayajulu 
689217ec208SDavid C Somayajulu         bzero(tq_name, sizeof (tq_name));
690217ec208SDavid C Somayajulu         snprintf(tq_name, sizeof (tq_name), "ql_err_tq");
691217ec208SDavid C Somayajulu 
692217ec208SDavid C Somayajulu         TASK_INIT(&ha->err_task, 0, qlnx_error_recovery_taskqueue, ha);
693217ec208SDavid C Somayajulu 
694217ec208SDavid C Somayajulu         ha->err_taskqueue = taskqueue_create(tq_name, M_NOWAIT,
695217ec208SDavid C Somayajulu                                 taskqueue_thread_enqueue, &ha->err_taskqueue);
696217ec208SDavid C Somayajulu 
697217ec208SDavid C Somayajulu         if (ha->err_taskqueue == NULL)
698217ec208SDavid C Somayajulu                 return (-1);
699217ec208SDavid C Somayajulu 
700217ec208SDavid C Somayajulu         taskqueue_start_threads(&ha->err_taskqueue, 1, PI_NET, "%s", tq_name);
701217ec208SDavid C Somayajulu 
702217ec208SDavid C Somayajulu         QL_DPRINT1(ha, "%p\n",ha->err_taskqueue);
703217ec208SDavid C Somayajulu 
704217ec208SDavid C Somayajulu         return (0);
705217ec208SDavid C Somayajulu }
706217ec208SDavid C Somayajulu 
707217ec208SDavid C Somayajulu static void
qlnx_destroy_error_recovery_taskqueue(qlnx_host_t * ha)708217ec208SDavid C Somayajulu qlnx_destroy_error_recovery_taskqueue(qlnx_host_t *ha)
709217ec208SDavid C Somayajulu {
710217ec208SDavid C Somayajulu         if (ha->err_taskqueue != NULL) {
711217ec208SDavid C Somayajulu                 taskqueue_drain(ha->err_taskqueue, &ha->err_task);
712217ec208SDavid C Somayajulu                 taskqueue_free(ha->err_taskqueue);
713217ec208SDavid C Somayajulu         }
714217ec208SDavid C Somayajulu 
715217ec208SDavid C Somayajulu         ha->err_taskqueue = NULL;
716217ec208SDavid C Somayajulu 
717217ec208SDavid C Somayajulu         return;
718217ec208SDavid C Somayajulu }
719217ec208SDavid C Somayajulu 
72011e25f0dSDavid C Somayajulu /*
72111e25f0dSDavid C Somayajulu  * Name:	qlnx_pci_attach
72211e25f0dSDavid C Somayajulu  * Function:	attaches the device to the operating system
72311e25f0dSDavid C Somayajulu  */
72411e25f0dSDavid C Somayajulu static int
qlnx_pci_attach(device_t dev)72511e25f0dSDavid C Somayajulu qlnx_pci_attach(device_t dev)
72611e25f0dSDavid C Somayajulu {
72711e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha = NULL;
728eb147f78SJohn Baldwin 	uint32_t	rsrc_len_reg __unused = 0;
72911e25f0dSDavid C Somayajulu 	uint32_t	rsrc_len_dbells = 0;
730eb147f78SJohn Baldwin 	uint32_t	rsrc_len_msix __unused = 0;
73111e25f0dSDavid C Somayajulu 	int		i;
73211e25f0dSDavid C Somayajulu 	uint32_t	mfw_ver;
733217ec208SDavid C Somayajulu 	uint32_t	num_sp_msix = 0;
734217ec208SDavid C Somayajulu 	uint32_t	num_rdma_irqs = 0;
73511e25f0dSDavid C Somayajulu 
73611e25f0dSDavid C Somayajulu         if ((ha = device_get_softc(dev)) == NULL) {
73711e25f0dSDavid C Somayajulu                 device_printf(dev, "cannot get softc\n");
73811e25f0dSDavid C Somayajulu                 return (ENOMEM);
73911e25f0dSDavid C Somayajulu         }
74011e25f0dSDavid C Somayajulu 
74111e25f0dSDavid C Somayajulu         memset(ha, 0, sizeof (qlnx_host_t));
74211e25f0dSDavid C Somayajulu 
743217ec208SDavid C Somayajulu         ha->device_id = pci_get_device(dev);
744217ec208SDavid C Somayajulu 
745217ec208SDavid C Somayajulu         if (qlnx_valid_device(ha) != 0) {
74611e25f0dSDavid C Somayajulu                 device_printf(dev, "device is not valid device\n");
74711e25f0dSDavid C Somayajulu                 return (ENXIO);
74811e25f0dSDavid C Somayajulu 	}
74911e25f0dSDavid C Somayajulu         ha->pci_func = pci_get_function(dev);
75011e25f0dSDavid C Somayajulu 
75111e25f0dSDavid C Somayajulu         ha->pci_dev = dev;
75211e25f0dSDavid C Somayajulu 
7531c45a62aSKeith Reynolds 	sx_init(&ha->hw_lock, "qlnx_hw_lock");
75411e25f0dSDavid C Somayajulu 
75511e25f0dSDavid C Somayajulu         ha->flags.lock_init = 1;
75611e25f0dSDavid C Somayajulu 
75711e25f0dSDavid C Somayajulu         pci_enable_busmaster(dev);
75811e25f0dSDavid C Somayajulu 
75911e25f0dSDavid C Somayajulu 	/*
76011e25f0dSDavid C Somayajulu 	 * map the PCI BARs
76111e25f0dSDavid C Somayajulu 	 */
76211e25f0dSDavid C Somayajulu 
76311e25f0dSDavid C Somayajulu         ha->reg_rid = PCIR_BAR(0);
76411e25f0dSDavid C Somayajulu         ha->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ha->reg_rid,
76511e25f0dSDavid C Somayajulu                                 RF_ACTIVE);
76611e25f0dSDavid C Somayajulu 
76711e25f0dSDavid C Somayajulu         if (ha->pci_reg == NULL) {
76811e25f0dSDavid C Somayajulu                 device_printf(dev, "unable to map BAR0\n");
76911e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
77011e25f0dSDavid C Somayajulu         }
77111e25f0dSDavid C Somayajulu 
77211e25f0dSDavid C Somayajulu         rsrc_len_reg = (uint32_t) bus_get_resource_count(dev, SYS_RES_MEMORY,
77311e25f0dSDavid C Somayajulu                                         ha->reg_rid);
77411e25f0dSDavid C Somayajulu 
77511e25f0dSDavid C Somayajulu 	ha->dbells_rid = PCIR_BAR(2);
776217ec208SDavid C Somayajulu 	rsrc_len_dbells = (uint32_t) bus_get_resource_count(dev,
777217ec208SDavid C Somayajulu 					SYS_RES_MEMORY,
778217ec208SDavid C Somayajulu 					ha->dbells_rid);
779217ec208SDavid C Somayajulu 	if (rsrc_len_dbells) {
78011e25f0dSDavid C Somayajulu 		ha->pci_dbells = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
78111e25f0dSDavid C Somayajulu 					&ha->dbells_rid, RF_ACTIVE);
78211e25f0dSDavid C Somayajulu 
78311e25f0dSDavid C Somayajulu 		if (ha->pci_dbells == NULL) {
78411e25f0dSDavid C Somayajulu 			device_printf(dev, "unable to map BAR1\n");
78511e25f0dSDavid C Somayajulu 			goto qlnx_pci_attach_err;
78611e25f0dSDavid C Somayajulu 		}
78711e25f0dSDavid C Somayajulu 		ha->dbells_phys_addr = (uint64_t)
788217ec208SDavid C Somayajulu 			bus_get_resource_start(dev, SYS_RES_MEMORY, ha->dbells_rid);
789217ec208SDavid C Somayajulu 
79011e25f0dSDavid C Somayajulu 		ha->dbells_size = rsrc_len_dbells;
791217ec208SDavid C Somayajulu 	} else {
792217ec208SDavid C Somayajulu 		if (qlnx_vf_device(ha) != 0) {
793217ec208SDavid C Somayajulu 			device_printf(dev, " BAR1 size is zero\n");
794217ec208SDavid C Somayajulu 			goto qlnx_pci_attach_err;
795217ec208SDavid C Somayajulu 		}
796217ec208SDavid C Somayajulu 	}
79711e25f0dSDavid C Somayajulu 
79811e25f0dSDavid C Somayajulu         ha->msix_rid = PCIR_BAR(4);
79911e25f0dSDavid C Somayajulu         ha->msix_bar = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
80011e25f0dSDavid C Somayajulu                         &ha->msix_rid, RF_ACTIVE);
80111e25f0dSDavid C Somayajulu 
80211e25f0dSDavid C Somayajulu         if (ha->msix_bar == NULL) {
80311e25f0dSDavid C Somayajulu                 device_printf(dev, "unable to map BAR2\n");
80411e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
80511e25f0dSDavid C Somayajulu 	}
80611e25f0dSDavid C Somayajulu 
80711e25f0dSDavid C Somayajulu         rsrc_len_msix = (uint32_t) bus_get_resource_count(dev, SYS_RES_MEMORY,
80811e25f0dSDavid C Somayajulu                                         ha->msix_rid);
809217ec208SDavid C Somayajulu 
810217ec208SDavid C Somayajulu 	ha->dbg_level = 0x0000;
811217ec208SDavid C Somayajulu 
812217ec208SDavid C Somayajulu 	QL_DPRINT1(ha, "\n\t\t\t"
813217ec208SDavid C Somayajulu 		"pci_dev = %p pci_reg = %p, reg_len = 0x%08x reg_rid = 0x%08x"
814217ec208SDavid C Somayajulu 		"\n\t\t\tdbells = %p, dbells_len = 0x%08x dbells_rid = 0x%08x"
815217ec208SDavid C Somayajulu 		"\n\t\t\tmsix = %p, msix_len = 0x%08x msix_rid = 0x%08x"
816217ec208SDavid C Somayajulu 		" msix_avail = 0x%x "
817217ec208SDavid C Somayajulu 		"\n\t\t\t[ncpus = %d]\n",
818217ec208SDavid C Somayajulu 		ha->pci_dev, ha->pci_reg, rsrc_len_reg,
819217ec208SDavid C Somayajulu 		ha->reg_rid, ha->pci_dbells, rsrc_len_dbells, ha->dbells_rid,
820217ec208SDavid C Somayajulu 		ha->msix_bar, rsrc_len_msix, ha->msix_rid, pci_msix_count(dev),
821217ec208SDavid C Somayajulu 		mp_ncpus);
82211e25f0dSDavid C Somayajulu 	/*
82311e25f0dSDavid C Somayajulu 	 * allocate dma tags
82411e25f0dSDavid C Somayajulu 	 */
82511e25f0dSDavid C Somayajulu 
82611e25f0dSDavid C Somayajulu 	if (qlnx_alloc_parent_dma_tag(ha))
82711e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
82811e25f0dSDavid C Somayajulu 
82911e25f0dSDavid C Somayajulu 	if (qlnx_alloc_tx_dma_tag(ha))
83011e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
83111e25f0dSDavid C Somayajulu 
83211e25f0dSDavid C Somayajulu 	if (qlnx_alloc_rx_dma_tag(ha))
83311e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
83411e25f0dSDavid C Somayajulu 
83511e25f0dSDavid C Somayajulu 
83611e25f0dSDavid C Somayajulu 	if (qlnx_init_hw(ha) != 0)
83711e25f0dSDavid C Somayajulu 		goto qlnx_pci_attach_err;
83811e25f0dSDavid C Somayajulu 
839217ec208SDavid C Somayajulu         ha->flags.hw_init = 1;
840217ec208SDavid C Somayajulu 
84145f13123SDavid C Somayajulu 	qlnx_get_params(ha);
84245f13123SDavid C Somayajulu 
84345f13123SDavid C Somayajulu 	if((pci_get_device(dev) == QLOGIC_PCI_DEVICE_ID_1644) &&
84445f13123SDavid C Somayajulu 		(qlnxe_queue_count == QLNX_DEFAULT_RSS)) {
84545f13123SDavid C Somayajulu 		qlnxe_queue_count = QLNX_MAX_RSS;
84645f13123SDavid C Somayajulu 	}
84745f13123SDavid C Somayajulu 
84811e25f0dSDavid C Somayajulu 	/*
84911e25f0dSDavid C Somayajulu 	 * Allocate MSI-x vectors
85011e25f0dSDavid C Somayajulu 	 */
851217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
85245f13123SDavid C Somayajulu 		if (qlnxe_queue_count == 0)
85345f13123SDavid C Somayajulu 			ha->num_rss = QLNX_DEFAULT_RSS;
85445f13123SDavid C Somayajulu 		else
85545f13123SDavid C Somayajulu 			ha->num_rss = qlnxe_queue_count;
85645f13123SDavid C Somayajulu 
857217ec208SDavid C Somayajulu 		num_sp_msix = ha->cdev.num_hwfns;
858217ec208SDavid C Somayajulu 	} else {
859217ec208SDavid C Somayajulu 		uint8_t max_rxq;
860217ec208SDavid C Somayajulu 		uint8_t max_txq;
861217ec208SDavid C Somayajulu 
862217ec208SDavid C Somayajulu 		ecore_vf_get_num_rxqs(&ha->cdev.hwfns[0], &max_rxq);
863217ec208SDavid C Somayajulu 		ecore_vf_get_num_rxqs(&ha->cdev.hwfns[0], &max_txq);
864217ec208SDavid C Somayajulu 
865217ec208SDavid C Somayajulu 		if (max_rxq < max_txq)
866217ec208SDavid C Somayajulu 			ha->num_rss = max_rxq;
867217ec208SDavid C Somayajulu 		else
868217ec208SDavid C Somayajulu 			ha->num_rss = max_txq;
869217ec208SDavid C Somayajulu 
870217ec208SDavid C Somayajulu 		if (ha->num_rss > QLNX_MAX_VF_RSS)
871217ec208SDavid C Somayajulu 			ha->num_rss = QLNX_MAX_VF_RSS;
872217ec208SDavid C Somayajulu 
873217ec208SDavid C Somayajulu 		num_sp_msix = 0;
874217ec208SDavid C Somayajulu 	}
875217ec208SDavid C Somayajulu 
876217ec208SDavid C Somayajulu 	if (ha->num_rss > mp_ncpus)
877217ec208SDavid C Somayajulu 		ha->num_rss = mp_ncpus;
878217ec208SDavid C Somayajulu 
87911e25f0dSDavid C Somayajulu 	ha->num_tc = QLNX_MAX_TC;
88011e25f0dSDavid C Somayajulu 
88111e25f0dSDavid C Somayajulu         ha->msix_count = pci_msix_count(dev);
88211e25f0dSDavid C Somayajulu 
883217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
884217ec208SDavid C Somayajulu 
885217ec208SDavid C Somayajulu 	num_rdma_irqs = qlnx_rdma_get_num_irqs(ha);
886217ec208SDavid C Somayajulu 
887217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
88811e25f0dSDavid C Somayajulu 
88911e25f0dSDavid C Somayajulu         if (!ha->msix_count ||
890217ec208SDavid C Somayajulu 		(ha->msix_count < (num_sp_msix + 1 + num_rdma_irqs))) {
89111e25f0dSDavid C Somayajulu                 device_printf(dev, "%s: msix_count[%d] not enough\n", __func__,
89211e25f0dSDavid C Somayajulu                         ha->msix_count);
89311e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
89411e25f0dSDavid C Somayajulu         }
89511e25f0dSDavid C Somayajulu 
896217ec208SDavid C Somayajulu 	if (ha->msix_count > (ha->num_rss + num_sp_msix + num_rdma_irqs))
897217ec208SDavid C Somayajulu 		ha->msix_count = ha->num_rss + num_sp_msix + num_rdma_irqs;
89811e25f0dSDavid C Somayajulu 	else
899217ec208SDavid C Somayajulu 		ha->num_rss = ha->msix_count - (num_sp_msix + num_rdma_irqs);
90011e25f0dSDavid C Somayajulu 
901217ec208SDavid C Somayajulu 	QL_DPRINT1(ha, "\n\t\t\t"
902217ec208SDavid C Somayajulu 		"pci_reg = %p, reg_len = 0x%08x reg_rid = 0x%08x"
903217ec208SDavid C Somayajulu 		"\n\t\t\tdbells = %p, dbells_len = 0x%08x dbells_rid = 0x%08x"
904217ec208SDavid C Somayajulu 		"\n\t\t\tmsix = %p, msix_len = 0x%08x msix_rid = 0x%08x"
905217ec208SDavid C Somayajulu 		" msix_avail = 0x%x msix_alloc = 0x%x"
90611e25f0dSDavid C Somayajulu 		"\n\t\t\t[ncpus = %d][num_rss = 0x%x] [num_tc = 0x%x]\n",
9077a377fbeSDavid C Somayajulu 		 ha->pci_reg, rsrc_len_reg,
90811e25f0dSDavid C Somayajulu 		ha->reg_rid, ha->pci_dbells, rsrc_len_dbells, ha->dbells_rid,
90911e25f0dSDavid C Somayajulu 		ha->msix_bar, rsrc_len_msix, ha->msix_rid, pci_msix_count(dev),
9107a377fbeSDavid C Somayajulu 		ha->msix_count, mp_ncpus, ha->num_rss, ha->num_tc);
911217ec208SDavid C Somayajulu 
91211e25f0dSDavid C Somayajulu         if (pci_alloc_msix(dev, &ha->msix_count)) {
91311e25f0dSDavid C Somayajulu                 device_printf(dev, "%s: pci_alloc_msix[%d] failed\n", __func__,
91411e25f0dSDavid C Somayajulu                         ha->msix_count);
91511e25f0dSDavid C Somayajulu                 ha->msix_count = 0;
91611e25f0dSDavid C Somayajulu                 goto qlnx_pci_attach_err;
91711e25f0dSDavid C Somayajulu         }
91811e25f0dSDavid C Somayajulu 
91911e25f0dSDavid C Somayajulu 	/*
92011e25f0dSDavid C Somayajulu 	 * Initialize slow path interrupt and task queue
92111e25f0dSDavid C Somayajulu 	 */
922217ec208SDavid C Somayajulu 
923217ec208SDavid C Somayajulu 	if (num_sp_msix) {
92411e25f0dSDavid C Somayajulu 		if (qlnx_create_sp_taskqueues(ha) != 0)
92511e25f0dSDavid C Somayajulu 			goto qlnx_pci_attach_err;
92611e25f0dSDavid C Somayajulu 
92711e25f0dSDavid C Somayajulu 		for (i = 0; i < ha->cdev.num_hwfns; i++) {
92811e25f0dSDavid C Somayajulu 			struct ecore_hwfn *p_hwfn = &ha->cdev.hwfns[i];
92911e25f0dSDavid C Somayajulu 
93011e25f0dSDavid C Somayajulu 			ha->sp_irq_rid[i] = i + 1;
93111e25f0dSDavid C Somayajulu 			ha->sp_irq[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
93211e25f0dSDavid C Somayajulu 						&ha->sp_irq_rid[i],
93311e25f0dSDavid C Somayajulu 						(RF_ACTIVE | RF_SHAREABLE));
93411e25f0dSDavid C Somayajulu 			if (ha->sp_irq[i] == NULL) {
93511e25f0dSDavid C Somayajulu                 		device_printf(dev,
93611e25f0dSDavid C Somayajulu 					"could not allocate mbx interrupt\n");
93711e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
93811e25f0dSDavid C Somayajulu 			}
93911e25f0dSDavid C Somayajulu 
94011e25f0dSDavid C Somayajulu 			if (bus_setup_intr(dev, ha->sp_irq[i],
94111e25f0dSDavid C Somayajulu 				(INTR_TYPE_NET | INTR_MPSAFE), NULL,
94211e25f0dSDavid C Somayajulu 				qlnx_sp_intr, p_hwfn, &ha->sp_handle[i])) {
94311e25f0dSDavid C Somayajulu 				device_printf(dev,
94411e25f0dSDavid C Somayajulu 					"could not setup slow path interrupt\n");
94511e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
94611e25f0dSDavid C Somayajulu 			}
94711e25f0dSDavid C Somayajulu 
9487a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "p_hwfn [%p] sp_irq_rid %d"
9497a377fbeSDavid C Somayajulu 				" sp_irq %p sp_handle %p\n", p_hwfn,
9507a377fbeSDavid C Somayajulu 				ha->sp_irq_rid[i], ha->sp_irq[i], ha->sp_handle[i]);
951217ec208SDavid C Somayajulu 		}
95211e25f0dSDavid C Somayajulu 	}
95311e25f0dSDavid C Somayajulu 
95411e25f0dSDavid C Somayajulu 	/*
95511e25f0dSDavid C Somayajulu 	 * initialize fast path interrupt
95611e25f0dSDavid C Somayajulu 	 */
95711e25f0dSDavid C Somayajulu 	if (qlnx_create_fp_taskqueues(ha) != 0)
95811e25f0dSDavid C Somayajulu 		goto qlnx_pci_attach_err;
95911e25f0dSDavid C Somayajulu 
96011e25f0dSDavid C Somayajulu         for (i = 0; i < ha->num_rss; i++) {
96111e25f0dSDavid C Somayajulu                 ha->irq_vec[i].rss_idx = i;
96211e25f0dSDavid C Somayajulu                 ha->irq_vec[i].ha = ha;
963217ec208SDavid C Somayajulu                 ha->irq_vec[i].irq_rid = (1 + num_sp_msix) + i;
96411e25f0dSDavid C Somayajulu 
96511e25f0dSDavid C Somayajulu                 ha->irq_vec[i].irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
96611e25f0dSDavid C Somayajulu                                 &ha->irq_vec[i].irq_rid,
96711e25f0dSDavid C Somayajulu                                 (RF_ACTIVE | RF_SHAREABLE));
96811e25f0dSDavid C Somayajulu 
96911e25f0dSDavid C Somayajulu                 if (ha->irq_vec[i].irq == NULL) {
97011e25f0dSDavid C Somayajulu                         device_printf(dev,
971217ec208SDavid C Somayajulu 				"could not allocate interrupt[%d] irq_rid = %d\n",
972217ec208SDavid C Somayajulu 				i, ha->irq_vec[i].irq_rid);
97311e25f0dSDavid C Somayajulu                         goto qlnx_pci_attach_err;
97411e25f0dSDavid C Somayajulu                 }
97511e25f0dSDavid C Somayajulu 
97611e25f0dSDavid C Somayajulu 		if (qlnx_alloc_tx_br(ha, &ha->fp_array[i])) {
97711e25f0dSDavid C Somayajulu                         device_printf(dev, "could not allocate tx_br[%d]\n", i);
97811e25f0dSDavid C Somayajulu                         goto qlnx_pci_attach_err;
97911e25f0dSDavid C Somayajulu 		}
98011e25f0dSDavid C Somayajulu 	}
98111e25f0dSDavid C Somayajulu 
982217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
98311e25f0dSDavid C Somayajulu 		callout_init(&ha->qlnx_callout, 1);
98411e25f0dSDavid C Somayajulu 		ha->flags.callout_init = 1;
98511e25f0dSDavid C Somayajulu 
98611e25f0dSDavid C Somayajulu 		for (i = 0; i < ha->cdev.num_hwfns; i++) {
98711e25f0dSDavid C Somayajulu 			if (qlnx_grc_dumpsize(ha, &ha->grcdump_size[i], i) != 0)
98811e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
98911e25f0dSDavid C Somayajulu 			if (ha->grcdump_size[i] == 0)
99011e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
99111e25f0dSDavid C Somayajulu 
99211e25f0dSDavid C Somayajulu 			ha->grcdump_size[i] = ha->grcdump_size[i] << 2;
9937a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "grcdump_size[%d] = 0x%08x\n",
9947a377fbeSDavid C Somayajulu 				i, ha->grcdump_size[i]);
99511e25f0dSDavid C Somayajulu 
99611e25f0dSDavid C Somayajulu 			ha->grcdump[i] = qlnx_zalloc(ha->grcdump_size[i]);
99711e25f0dSDavid C Somayajulu 			if (ha->grcdump[i] == NULL) {
99811e25f0dSDavid C Somayajulu 				device_printf(dev, "grcdump alloc[%d] failed\n", i);
99911e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
100011e25f0dSDavid C Somayajulu 			}
100111e25f0dSDavid C Somayajulu 
100211e25f0dSDavid C Somayajulu 			if (qlnx_idle_chk_size(ha, &ha->idle_chk_size[i], i) != 0)
100311e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
100411e25f0dSDavid C Somayajulu 			if (ha->idle_chk_size[i] == 0)
100511e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
100611e25f0dSDavid C Somayajulu 
100711e25f0dSDavid C Somayajulu 			ha->idle_chk_size[i] = ha->idle_chk_size[i] << 2;
10087a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "idle_chk_size[%d] = 0x%08x\n",
10097a377fbeSDavid C Somayajulu 				i, ha->idle_chk_size[i]);
101011e25f0dSDavid C Somayajulu 
101111e25f0dSDavid C Somayajulu 			ha->idle_chk[i] = qlnx_zalloc(ha->idle_chk_size[i]);
101211e25f0dSDavid C Somayajulu 
101311e25f0dSDavid C Somayajulu 			if (ha->idle_chk[i] == NULL) {
101411e25f0dSDavid C Somayajulu 				device_printf(dev, "idle_chk alloc failed\n");
101511e25f0dSDavid C Somayajulu 				goto qlnx_pci_attach_err;
101611e25f0dSDavid C Somayajulu 			}
101711e25f0dSDavid C Somayajulu 		}
101811e25f0dSDavid C Somayajulu 
1019217ec208SDavid C Somayajulu 		if (qlnx_create_error_recovery_taskqueue(ha) != 0)
1020217ec208SDavid C Somayajulu 			goto qlnx_pci_attach_err;
1021217ec208SDavid C Somayajulu 	}
102211e25f0dSDavid C Somayajulu 
1023217ec208SDavid C Somayajulu 	if (qlnx_slowpath_start(ha) != 0)
1024217ec208SDavid C Somayajulu 		goto qlnx_pci_attach_err;
1025217ec208SDavid C Somayajulu 	else
102611e25f0dSDavid C Somayajulu 		ha->flags.slowpath_start = 1;
102711e25f0dSDavid C Somayajulu 
1028217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
102911e25f0dSDavid C Somayajulu 		if (qlnx_get_flash_size(ha, &ha->flash_size) != 0) {
103011e25f0dSDavid C Somayajulu 			qlnx_mdelay(__func__, 1000);
103111e25f0dSDavid C Somayajulu 			qlnx_trigger_dump(ha);
103211e25f0dSDavid C Somayajulu 
103311e25f0dSDavid C Somayajulu 			goto qlnx_pci_attach_err0;
103411e25f0dSDavid C Somayajulu 		}
103511e25f0dSDavid C Somayajulu 
103611e25f0dSDavid C Somayajulu 		if (qlnx_get_mfw_version(ha, &mfw_ver) != 0) {
103711e25f0dSDavid C Somayajulu 			qlnx_mdelay(__func__, 1000);
103811e25f0dSDavid C Somayajulu 			qlnx_trigger_dump(ha);
103911e25f0dSDavid C Somayajulu 
104011e25f0dSDavid C Somayajulu 			goto qlnx_pci_attach_err0;
104111e25f0dSDavid C Somayajulu 		}
1042217ec208SDavid C Somayajulu 	} else {
1043217ec208SDavid C Somayajulu 		struct ecore_hwfn *p_hwfn = &ha->cdev.hwfns[0];
1044217ec208SDavid C Somayajulu 		ecore_mcp_get_mfw_ver(p_hwfn, NULL, &mfw_ver, NULL);
1045217ec208SDavid C Somayajulu 	}
1046217ec208SDavid C Somayajulu 
104711e25f0dSDavid C Somayajulu 	snprintf(ha->mfw_ver, sizeof(ha->mfw_ver), "%d.%d.%d.%d",
104811e25f0dSDavid C Somayajulu 		((mfw_ver >> 24) & 0xFF), ((mfw_ver >> 16) & 0xFF),
104911e25f0dSDavid C Somayajulu 		((mfw_ver >> 8) & 0xFF), (mfw_ver & 0xFF));
105011e25f0dSDavid C Somayajulu 	snprintf(ha->stormfw_ver, sizeof(ha->stormfw_ver), "%d.%d.%d.%d",
105111e25f0dSDavid C Somayajulu 		FW_MAJOR_VERSION, FW_MINOR_VERSION, FW_REVISION_VERSION,
105211e25f0dSDavid C Somayajulu 		FW_ENGINEERING_VERSION);
105311e25f0dSDavid C Somayajulu 
10547a377fbeSDavid C Somayajulu 	QL_DPRINT1(ha, "STORM_FW version %s MFW version %s\n",
10557a377fbeSDavid C Somayajulu 		 ha->stormfw_ver, ha->mfw_ver);
105611e25f0dSDavid C Somayajulu 
105711e25f0dSDavid C Somayajulu 	qlnx_init_ifnet(dev, ha);
105811e25f0dSDavid C Somayajulu 
105911e25f0dSDavid C Somayajulu 	/*
106011e25f0dSDavid C Somayajulu 	 * add sysctls
106111e25f0dSDavid C Somayajulu 	 */
106211e25f0dSDavid C Somayajulu 	qlnx_add_sysctls(ha);
106311e25f0dSDavid C Somayajulu 
106411e25f0dSDavid C Somayajulu qlnx_pci_attach_err0:
106511e25f0dSDavid C Somayajulu         /*
106611e25f0dSDavid C Somayajulu 	 * create ioctl device interface
106711e25f0dSDavid C Somayajulu 	 */
1068217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
106911e25f0dSDavid C Somayajulu 		if (qlnx_make_cdev(ha)) {
107011e25f0dSDavid C Somayajulu 			device_printf(dev, "%s: ql_make_cdev failed\n", __func__);
107111e25f0dSDavid C Somayajulu 			goto qlnx_pci_attach_err;
107211e25f0dSDavid C Somayajulu 		}
107311e25f0dSDavid C Somayajulu 
1074217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
1075217ec208SDavid C Somayajulu 		qlnx_rdma_dev_add(ha);
1076217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
1077217ec208SDavid C Somayajulu 	}
1078217ec208SDavid C Somayajulu 
1079217ec208SDavid C Somayajulu #ifndef QLNX_VF
1080217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
1081217ec208SDavid C Somayajulu 
1082217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0)
1083217ec208SDavid C Somayajulu 		qlnx_initialize_sriov(ha);
1084217ec208SDavid C Somayajulu 
1085217ec208SDavid C Somayajulu #endif /* #ifdef CONFIG_ECORE_SRIOV */
1086217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_VF */
1087217ec208SDavid C Somayajulu 
10887a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "success\n");
108911e25f0dSDavid C Somayajulu 
109011e25f0dSDavid C Somayajulu         return (0);
109111e25f0dSDavid C Somayajulu 
109211e25f0dSDavid C Somayajulu qlnx_pci_attach_err:
109311e25f0dSDavid C Somayajulu 
109411e25f0dSDavid C Somayajulu 	qlnx_release(ha);
109511e25f0dSDavid C Somayajulu 
109611e25f0dSDavid C Somayajulu 	return (ENXIO);
109711e25f0dSDavid C Somayajulu }
109811e25f0dSDavid C Somayajulu 
109911e25f0dSDavid C Somayajulu /*
110011e25f0dSDavid C Somayajulu  * Name:	qlnx_pci_detach
110111e25f0dSDavid C Somayajulu  * Function:	Unhooks the device from the operating system
110211e25f0dSDavid C Somayajulu  */
110311e25f0dSDavid C Somayajulu static int
qlnx_pci_detach(device_t dev)110411e25f0dSDavid C Somayajulu qlnx_pci_detach(device_t dev)
110511e25f0dSDavid C Somayajulu {
110611e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha = NULL;
110711e25f0dSDavid C Somayajulu 
110811e25f0dSDavid C Somayajulu         if ((ha = device_get_softc(dev)) == NULL) {
1109217ec208SDavid C Somayajulu                 device_printf(dev, "%s: cannot get softc\n", __func__);
111011e25f0dSDavid C Somayajulu                 return (ENOMEM);
111111e25f0dSDavid C Somayajulu         }
111211e25f0dSDavid C Somayajulu 
1113217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
1114217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
1115217ec208SDavid C Somayajulu 		int ret;
1116217ec208SDavid C Somayajulu 
1117217ec208SDavid C Somayajulu 		ret = pci_iov_detach(dev);
1118217ec208SDavid C Somayajulu 		if (ret) {
1119217ec208SDavid C Somayajulu                 	device_printf(dev, "%s: SRIOV in use\n", __func__);
1120217ec208SDavid C Somayajulu 			return (ret);
1121217ec208SDavid C Somayajulu 		}
1122217ec208SDavid C Somayajulu 
1123217ec208SDavid C Somayajulu #endif /* #ifdef CONFIG_ECORE_SRIOV */
1124217ec208SDavid C Somayajulu 
1125217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
1126217ec208SDavid C Somayajulu 		if (qlnx_rdma_dev_remove(ha) != 0)
1127217ec208SDavid C Somayajulu 			return (EBUSY);
1128217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
1129217ec208SDavid C Somayajulu 	}
1130217ec208SDavid C Somayajulu 
113111e25f0dSDavid C Somayajulu 	QLNX_LOCK(ha);
113211e25f0dSDavid C Somayajulu 	qlnx_stop(ha);
113311e25f0dSDavid C Somayajulu 	QLNX_UNLOCK(ha);
113411e25f0dSDavid C Somayajulu 
113511e25f0dSDavid C Somayajulu 	qlnx_release(ha);
113611e25f0dSDavid C Somayajulu 
113711e25f0dSDavid C Somayajulu         return (0);
113811e25f0dSDavid C Somayajulu }
113911e25f0dSDavid C Somayajulu 
1140217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
1141217ec208SDavid C Somayajulu 
1142217ec208SDavid C Somayajulu static uint8_t
qlnx_get_personality(uint8_t pci_func)1143217ec208SDavid C Somayajulu qlnx_get_personality(uint8_t pci_func)
1144217ec208SDavid C Somayajulu {
1145217ec208SDavid C Somayajulu 	uint8_t personality;
1146217ec208SDavid C Somayajulu 
1147217ec208SDavid C Somayajulu 	personality = (qlnxe_rdma_configuration >>
1148217ec208SDavid C Somayajulu 				(pci_func * QLNX_PERSONALITY_BITS_PER_FUNC)) &
1149217ec208SDavid C Somayajulu 				QLNX_PERSONALIY_MASK;
1150217ec208SDavid C Somayajulu 	return (personality);
1151217ec208SDavid C Somayajulu }
1152217ec208SDavid C Somayajulu 
1153217ec208SDavid C Somayajulu static void
qlnx_set_personality(qlnx_host_t * ha)1154217ec208SDavid C Somayajulu qlnx_set_personality(qlnx_host_t *ha)
1155217ec208SDavid C Somayajulu {
1156217ec208SDavid C Somayajulu 	uint8_t personality;
1157217ec208SDavid C Somayajulu 
1158217ec208SDavid C Somayajulu 	personality = qlnx_get_personality(ha->pci_func);
1159217ec208SDavid C Somayajulu 
1160217ec208SDavid C Somayajulu 	switch (personality) {
1161217ec208SDavid C Somayajulu 	case QLNX_PERSONALITY_DEFAULT:
1162217ec208SDavid C Somayajulu                	device_printf(ha->pci_dev, "%s: DEFAULT\n",
1163217ec208SDavid C Somayajulu 			__func__);
1164217ec208SDavid C Somayajulu 		ha->personality = ECORE_PCI_DEFAULT;
1165217ec208SDavid C Somayajulu 		break;
1166217ec208SDavid C Somayajulu 
1167217ec208SDavid C Somayajulu 	case QLNX_PERSONALITY_ETH_ONLY:
1168217ec208SDavid C Somayajulu                	device_printf(ha->pci_dev, "%s: ETH_ONLY\n",
1169217ec208SDavid C Somayajulu 			__func__);
1170217ec208SDavid C Somayajulu 		ha->personality = ECORE_PCI_ETH;
1171217ec208SDavid C Somayajulu 		break;
1172217ec208SDavid C Somayajulu 
1173217ec208SDavid C Somayajulu 	case QLNX_PERSONALITY_ETH_IWARP:
1174217ec208SDavid C Somayajulu                	device_printf(ha->pci_dev, "%s: ETH_IWARP\n",
1175217ec208SDavid C Somayajulu 			__func__);
1176217ec208SDavid C Somayajulu 		ha->personality = ECORE_PCI_ETH_IWARP;
1177217ec208SDavid C Somayajulu 		break;
1178217ec208SDavid C Somayajulu 
1179217ec208SDavid C Somayajulu 	case QLNX_PERSONALITY_ETH_ROCE:
1180217ec208SDavid C Somayajulu                	device_printf(ha->pci_dev, "%s: ETH_ROCE\n",
1181217ec208SDavid C Somayajulu 			__func__);
1182217ec208SDavid C Somayajulu 		ha->personality = ECORE_PCI_ETH_ROCE;
1183217ec208SDavid C Somayajulu 		break;
1184217ec208SDavid C Somayajulu 	}
1185217ec208SDavid C Somayajulu 
1186217ec208SDavid C Somayajulu 	return;
1187217ec208SDavid C Somayajulu }
1188217ec208SDavid C Somayajulu 
1189217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
1190217ec208SDavid C Somayajulu 
119111e25f0dSDavid C Somayajulu static int
qlnx_init_hw(qlnx_host_t * ha)119211e25f0dSDavid C Somayajulu qlnx_init_hw(qlnx_host_t *ha)
119311e25f0dSDavid C Somayajulu {
119411e25f0dSDavid C Somayajulu 	int				rval = 0;
119511e25f0dSDavid C Somayajulu 	struct ecore_hw_prepare_params	params;
119611e25f0dSDavid C Somayajulu 
11971c45a62aSKeith Reynolds         ha->cdev.ha = ha;
119811e25f0dSDavid C Somayajulu 	ecore_init_struct(&ha->cdev);
119911e25f0dSDavid C Somayajulu 
120011e25f0dSDavid C Somayajulu 	/* ha->dp_module = ECORE_MSG_PROBE |
120111e25f0dSDavid C Somayajulu 				ECORE_MSG_INTR |
120211e25f0dSDavid C Somayajulu 				ECORE_MSG_SP |
120311e25f0dSDavid C Somayajulu 				ECORE_MSG_LINK |
120411e25f0dSDavid C Somayajulu 				ECORE_MSG_SPQ |
120511e25f0dSDavid C Somayajulu 				ECORE_MSG_RDMA;
120611e25f0dSDavid C Somayajulu 	ha->dp_level = ECORE_LEVEL_VERBOSE;*/
1207217ec208SDavid C Somayajulu 	//ha->dp_module = ECORE_MSG_RDMA | ECORE_MSG_INTR | ECORE_MSG_LL2;
120811e25f0dSDavid C Somayajulu 	ha->dp_level = ECORE_LEVEL_NOTICE;
1209217ec208SDavid C Somayajulu 	//ha->dp_level = ECORE_LEVEL_VERBOSE;
121011e25f0dSDavid C Somayajulu 
121111e25f0dSDavid C Somayajulu 	ecore_init_dp(&ha->cdev, ha->dp_module, ha->dp_level, ha->pci_dev);
121211e25f0dSDavid C Somayajulu 
121311e25f0dSDavid C Somayajulu 	ha->cdev.regview = ha->pci_reg;
1214217ec208SDavid C Somayajulu 
1215217ec208SDavid C Somayajulu 	ha->personality = ECORE_PCI_DEFAULT;
1216217ec208SDavid C Somayajulu 
1217217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0) {
1218217ec208SDavid C Somayajulu 		ha->cdev.b_is_vf = true;
1219217ec208SDavid C Somayajulu 
1220217ec208SDavid C Somayajulu 		if (ha->pci_dbells != NULL) {
1221217ec208SDavid C Somayajulu 			ha->cdev.doorbells = ha->pci_dbells;
1222217ec208SDavid C Somayajulu 			ha->cdev.db_phys_addr = ha->dbells_phys_addr;
1223217ec208SDavid C Somayajulu 			ha->cdev.db_size = ha->dbells_size;
1224217ec208SDavid C Somayajulu 		} else {
1225217ec208SDavid C Somayajulu 			ha->pci_dbells = ha->pci_reg;
1226217ec208SDavid C Somayajulu 		}
1227217ec208SDavid C Somayajulu 	} else {
122811e25f0dSDavid C Somayajulu 		ha->cdev.doorbells = ha->pci_dbells;
122911e25f0dSDavid C Somayajulu 		ha->cdev.db_phys_addr = ha->dbells_phys_addr;
123011e25f0dSDavid C Somayajulu 		ha->cdev.db_size = ha->dbells_size;
123111e25f0dSDavid C Somayajulu 
1232217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
123311e25f0dSDavid C Somayajulu 
1234217ec208SDavid C Somayajulu 		if (qlnx_rdma_supported(ha) == 0)
1235217ec208SDavid C Somayajulu 			qlnx_set_personality(ha);
1236217ec208SDavid C Somayajulu 
1237217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
1238217ec208SDavid C Somayajulu 	}
1239217ec208SDavid C Somayajulu 	QL_DPRINT2(ha, "%s: %s\n", __func__,
1240217ec208SDavid C Somayajulu 		(ha->personality == ECORE_PCI_ETH_IWARP ? "iwarp": "ethernet"));
1241217ec208SDavid C Somayajulu 
1242217ec208SDavid C Somayajulu 	bzero(&params, sizeof (struct ecore_hw_prepare_params));
124311e25f0dSDavid C Somayajulu 
124411e25f0dSDavid C Somayajulu 	params.personality = ha->personality;
124511e25f0dSDavid C Somayajulu 
124611e25f0dSDavid C Somayajulu 	params.drv_resc_alloc = false;
124711e25f0dSDavid C Somayajulu 	params.chk_reg_fifo = false;
124811e25f0dSDavid C Somayajulu 	params.initiate_pf_flr = true;
124911e25f0dSDavid C Somayajulu 	params.epoch = 0;
125011e25f0dSDavid C Somayajulu 
125111e25f0dSDavid C Somayajulu 	ecore_hw_prepare(&ha->cdev, &params);
125211e25f0dSDavid C Somayajulu 
125311e25f0dSDavid C Somayajulu 	qlnx_set_id(&ha->cdev, qlnx_name_str, qlnx_ver_str);
125411e25f0dSDavid C Somayajulu 
1255217ec208SDavid C Somayajulu 	QL_DPRINT1(ha, "ha = %p cdev = %p p_hwfn = %p\n",
1256217ec208SDavid C Somayajulu 		ha, &ha->cdev, &ha->cdev.hwfns[0]);
1257217ec208SDavid C Somayajulu 
125811e25f0dSDavid C Somayajulu 	return (rval);
125911e25f0dSDavid C Somayajulu }
126011e25f0dSDavid C Somayajulu 
126111e25f0dSDavid C Somayajulu static void
qlnx_release(qlnx_host_t * ha)126211e25f0dSDavid C Somayajulu qlnx_release(qlnx_host_t *ha)
126311e25f0dSDavid C Somayajulu {
126411e25f0dSDavid C Somayajulu         device_t	dev;
126511e25f0dSDavid C Somayajulu         int		i;
126611e25f0dSDavid C Somayajulu 
126711e25f0dSDavid C Somayajulu         dev = ha->pci_dev;
126811e25f0dSDavid C Somayajulu 
12697a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
127011e25f0dSDavid C Somayajulu 
127111e25f0dSDavid C Somayajulu 	for (i = 0; i < QLNX_MAX_HW_FUNCS; i++) {
127211e25f0dSDavid C Somayajulu 		if (ha->idle_chk[i] != NULL) {
127311e25f0dSDavid C Somayajulu 			free(ha->idle_chk[i], M_QLNXBUF);
127411e25f0dSDavid C Somayajulu 			ha->idle_chk[i] = NULL;
127511e25f0dSDavid C Somayajulu 		}
127611e25f0dSDavid C Somayajulu 
127711e25f0dSDavid C Somayajulu 		if (ha->grcdump[i] != NULL) {
127811e25f0dSDavid C Somayajulu 			free(ha->grcdump[i], M_QLNXBUF);
127911e25f0dSDavid C Somayajulu 			ha->grcdump[i] = NULL;
128011e25f0dSDavid C Somayajulu 		}
128111e25f0dSDavid C Somayajulu 	}
128211e25f0dSDavid C Somayajulu 
128311e25f0dSDavid C Somayajulu         if (ha->flags.callout_init)
128411e25f0dSDavid C Somayajulu                 callout_drain(&ha->qlnx_callout);
128511e25f0dSDavid C Somayajulu 
128611e25f0dSDavid C Somayajulu 	if (ha->flags.slowpath_start) {
128711e25f0dSDavid C Somayajulu 		qlnx_slowpath_stop(ha);
128811e25f0dSDavid C Somayajulu 	}
128911e25f0dSDavid C Somayajulu 
1290217ec208SDavid C Somayajulu         if (ha->flags.hw_init)
129111e25f0dSDavid C Somayajulu 		ecore_hw_remove(&ha->cdev);
129211e25f0dSDavid C Somayajulu 
129311e25f0dSDavid C Somayajulu         qlnx_del_cdev(ha);
129411e25f0dSDavid C Somayajulu 
129511e25f0dSDavid C Somayajulu         if (ha->ifp != NULL)
129611e25f0dSDavid C Somayajulu                 ether_ifdetach(ha->ifp);
129711e25f0dSDavid C Somayajulu 
129811e25f0dSDavid C Somayajulu 	qlnx_free_tx_dma_tag(ha);
129911e25f0dSDavid C Somayajulu 
130011e25f0dSDavid C Somayajulu 	qlnx_free_rx_dma_tag(ha);
130111e25f0dSDavid C Somayajulu 
130211e25f0dSDavid C Somayajulu 	qlnx_free_parent_dma_tag(ha);
130311e25f0dSDavid C Somayajulu 
1304217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
1305217ec208SDavid C Somayajulu 		qlnx_destroy_error_recovery_taskqueue(ha);
1306217ec208SDavid C Somayajulu 	}
1307217ec208SDavid C Somayajulu 
130811e25f0dSDavid C Somayajulu         for (i = 0; i < ha->num_rss; i++) {
130911e25f0dSDavid C Somayajulu 		struct qlnx_fastpath *fp = &ha->fp_array[i];
131011e25f0dSDavid C Somayajulu 
131111e25f0dSDavid C Somayajulu                 if (ha->irq_vec[i].handle) {
131211e25f0dSDavid C Somayajulu                         (void)bus_teardown_intr(dev, ha->irq_vec[i].irq,
131311e25f0dSDavid C Somayajulu                                         ha->irq_vec[i].handle);
131411e25f0dSDavid C Somayajulu                 }
131511e25f0dSDavid C Somayajulu 
131611e25f0dSDavid C Somayajulu                 if (ha->irq_vec[i].irq) {
131711e25f0dSDavid C Somayajulu                         (void)bus_release_resource(dev, SYS_RES_IRQ,
131811e25f0dSDavid C Somayajulu                                 ha->irq_vec[i].irq_rid,
131911e25f0dSDavid C Somayajulu                                 ha->irq_vec[i].irq);
132011e25f0dSDavid C Somayajulu                 }
132111e25f0dSDavid C Somayajulu 
132211e25f0dSDavid C Somayajulu 		qlnx_free_tx_br(ha, fp);
132311e25f0dSDavid C Somayajulu         }
132411e25f0dSDavid C Somayajulu 	qlnx_destroy_fp_taskqueues(ha);
132511e25f0dSDavid C Somayajulu 
132611e25f0dSDavid C Somayajulu  	for (i = 0; i < ha->cdev.num_hwfns; i++) {
132711e25f0dSDavid C Somayajulu         	if (ha->sp_handle[i])
132811e25f0dSDavid C Somayajulu                 	(void)bus_teardown_intr(dev, ha->sp_irq[i],
132911e25f0dSDavid C Somayajulu 				ha->sp_handle[i]);
133011e25f0dSDavid C Somayajulu 
133111e25f0dSDavid C Somayajulu         	if (ha->sp_irq[i])
133211e25f0dSDavid C Somayajulu 			(void) bus_release_resource(dev, SYS_RES_IRQ,
133311e25f0dSDavid C Somayajulu 				ha->sp_irq_rid[i], ha->sp_irq[i]);
133411e25f0dSDavid C Somayajulu 	}
133511e25f0dSDavid C Somayajulu 
133611e25f0dSDavid C Somayajulu 	qlnx_destroy_sp_taskqueues(ha);
133711e25f0dSDavid C Somayajulu 
133811e25f0dSDavid C Somayajulu         if (ha->msix_count)
133911e25f0dSDavid C Somayajulu                 pci_release_msi(dev);
134011e25f0dSDavid C Somayajulu 
134111e25f0dSDavid C Somayajulu         if (ha->flags.lock_init) {
13421c45a62aSKeith Reynolds                 sx_destroy(&ha->hw_lock);
134311e25f0dSDavid C Somayajulu         }
134411e25f0dSDavid C Somayajulu 
134511e25f0dSDavid C Somayajulu         if (ha->pci_reg)
134611e25f0dSDavid C Somayajulu                 (void) bus_release_resource(dev, SYS_RES_MEMORY, ha->reg_rid,
134711e25f0dSDavid C Somayajulu                                 ha->pci_reg);
134811e25f0dSDavid C Somayajulu 
1349217ec208SDavid C Somayajulu         if (ha->dbells_size && ha->pci_dbells)
135011e25f0dSDavid C Somayajulu                 (void) bus_release_resource(dev, SYS_RES_MEMORY, ha->dbells_rid,
135111e25f0dSDavid C Somayajulu                                 ha->pci_dbells);
135211e25f0dSDavid C Somayajulu 
135311e25f0dSDavid C Somayajulu         if (ha->msix_bar)
135411e25f0dSDavid C Somayajulu                 (void) bus_release_resource(dev, SYS_RES_MEMORY, ha->msix_rid,
135511e25f0dSDavid C Somayajulu                                 ha->msix_bar);
135611e25f0dSDavid C Somayajulu 
13577a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
135811e25f0dSDavid C Somayajulu 	return;
135911e25f0dSDavid C Somayajulu }
136011e25f0dSDavid C Somayajulu 
136111e25f0dSDavid C Somayajulu static void
qlnx_trigger_dump(qlnx_host_t * ha)136211e25f0dSDavid C Somayajulu qlnx_trigger_dump(qlnx_host_t *ha)
136311e25f0dSDavid C Somayajulu {
136411e25f0dSDavid C Somayajulu 	int	i;
136511e25f0dSDavid C Somayajulu 
136611e25f0dSDavid C Somayajulu 	if (ha->ifp != NULL)
1367727bfe38SJustin Hibbits 		if_setdrvflagbits(ha->ifp, 0, (IFF_DRV_OACTIVE | IFF_DRV_RUNNING));
136811e25f0dSDavid C Somayajulu 
13697a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
137011e25f0dSDavid C Somayajulu 
1371217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
1372217ec208SDavid C Somayajulu 		return;
1373217ec208SDavid C Somayajulu 
1374217ec208SDavid C Somayajulu 	ha->error_recovery = 1;
1375217ec208SDavid C Somayajulu 
137611e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
137711e25f0dSDavid C Somayajulu 		qlnx_grc_dump(ha, &ha->grcdump_dwords[i], i);
137811e25f0dSDavid C Somayajulu 		qlnx_idle_chk(ha, &ha->idle_chk_dwords[i], i);
137911e25f0dSDavid C Somayajulu 	}
138011e25f0dSDavid C Somayajulu 
13817a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
138211e25f0dSDavid C Somayajulu 
138311e25f0dSDavid C Somayajulu 	return;
138411e25f0dSDavid C Somayajulu }
138511e25f0dSDavid C Somayajulu 
138611e25f0dSDavid C Somayajulu static int
qlnx_trigger_dump_sysctl(SYSCTL_HANDLER_ARGS)138711e25f0dSDavid C Somayajulu qlnx_trigger_dump_sysctl(SYSCTL_HANDLER_ARGS)
138811e25f0dSDavid C Somayajulu {
138911e25f0dSDavid C Somayajulu         int		err, ret = 0;
139011e25f0dSDavid C Somayajulu         qlnx_host_t	*ha;
139111e25f0dSDavid C Somayajulu 
139211e25f0dSDavid C Somayajulu         err = sysctl_handle_int(oidp, &ret, 0, req);
139311e25f0dSDavid C Somayajulu 
139411e25f0dSDavid C Somayajulu         if (err || !req->newptr)
139511e25f0dSDavid C Somayajulu                 return (err);
139611e25f0dSDavid C Somayajulu 
139711e25f0dSDavid C Somayajulu         if (ret == 1) {
139811e25f0dSDavid C Somayajulu                 ha = (qlnx_host_t *)arg1;
139911e25f0dSDavid C Somayajulu                 qlnx_trigger_dump(ha);
140011e25f0dSDavid C Somayajulu         }
140111e25f0dSDavid C Somayajulu         return (err);
140211e25f0dSDavid C Somayajulu }
140311e25f0dSDavid C Somayajulu 
140411e25f0dSDavid C Somayajulu static int
qlnx_set_tx_coalesce(SYSCTL_HANDLER_ARGS)140511e25f0dSDavid C Somayajulu qlnx_set_tx_coalesce(SYSCTL_HANDLER_ARGS)
140611e25f0dSDavid C Somayajulu {
140711e25f0dSDavid C Somayajulu         int			err, i, ret = 0, usecs = 0;
140811e25f0dSDavid C Somayajulu         qlnx_host_t		*ha;
140911e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
141011e25f0dSDavid C Somayajulu 	struct qlnx_fastpath	*fp;
141111e25f0dSDavid C Somayajulu 
141211e25f0dSDavid C Somayajulu         err = sysctl_handle_int(oidp, &usecs, 0, req);
141311e25f0dSDavid C Somayajulu 
141411e25f0dSDavid C Somayajulu         if (err || !req->newptr || !usecs || (usecs > 255))
141511e25f0dSDavid C Somayajulu                 return (err);
141611e25f0dSDavid C Somayajulu 
141711e25f0dSDavid C Somayajulu         ha = (qlnx_host_t *)arg1;
141811e25f0dSDavid C Somayajulu 
1419217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
1420217ec208SDavid C Somayajulu 		return (-1);
1421217ec208SDavid C Somayajulu 
142211e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
142311e25f0dSDavid C Somayajulu 		p_hwfn = &ha->cdev.hwfns[(i % ha->cdev.num_hwfns)];
142411e25f0dSDavid C Somayajulu 
142511e25f0dSDavid C Somayajulu         	fp = &ha->fp_array[i];
142611e25f0dSDavid C Somayajulu 
142711e25f0dSDavid C Somayajulu 		if (fp->txq[0]->handle != NULL) {
142811e25f0dSDavid C Somayajulu 			ret = ecore_set_queue_coalesce(p_hwfn, 0,
142911e25f0dSDavid C Somayajulu 					(uint16_t)usecs, fp->txq[0]->handle);
143011e25f0dSDavid C Somayajulu 		}
143111e25f0dSDavid C Somayajulu         }
143211e25f0dSDavid C Somayajulu 
143311e25f0dSDavid C Somayajulu 	if (!ret)
143411e25f0dSDavid C Somayajulu 		ha->tx_coalesce_usecs = (uint8_t)usecs;
143511e25f0dSDavid C Somayajulu 
143611e25f0dSDavid C Somayajulu         return (err);
143711e25f0dSDavid C Somayajulu }
143811e25f0dSDavid C Somayajulu 
143911e25f0dSDavid C Somayajulu static int
qlnx_set_rx_coalesce(SYSCTL_HANDLER_ARGS)144011e25f0dSDavid C Somayajulu qlnx_set_rx_coalesce(SYSCTL_HANDLER_ARGS)
144111e25f0dSDavid C Somayajulu {
144211e25f0dSDavid C Somayajulu         int			err, i, ret = 0, usecs = 0;
144311e25f0dSDavid C Somayajulu         qlnx_host_t		*ha;
144411e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
144511e25f0dSDavid C Somayajulu 	struct qlnx_fastpath	*fp;
144611e25f0dSDavid C Somayajulu 
144711e25f0dSDavid C Somayajulu         err = sysctl_handle_int(oidp, &usecs, 0, req);
144811e25f0dSDavid C Somayajulu 
144911e25f0dSDavid C Somayajulu         if (err || !req->newptr || !usecs || (usecs > 255))
145011e25f0dSDavid C Somayajulu                 return (err);
145111e25f0dSDavid C Somayajulu 
145211e25f0dSDavid C Somayajulu         ha = (qlnx_host_t *)arg1;
145311e25f0dSDavid C Somayajulu 
1454217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
1455217ec208SDavid C Somayajulu 		return (-1);
1456217ec208SDavid C Somayajulu 
145711e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
145811e25f0dSDavid C Somayajulu 		p_hwfn = &ha->cdev.hwfns[(i % ha->cdev.num_hwfns)];
145911e25f0dSDavid C Somayajulu 
146011e25f0dSDavid C Somayajulu         	fp = &ha->fp_array[i];
146111e25f0dSDavid C Somayajulu 
146211e25f0dSDavid C Somayajulu 		if (fp->rxq->handle != NULL) {
146311e25f0dSDavid C Somayajulu 			ret = ecore_set_queue_coalesce(p_hwfn, (uint16_t)usecs,
146411e25f0dSDavid C Somayajulu 					 0, fp->rxq->handle);
146511e25f0dSDavid C Somayajulu 		}
146611e25f0dSDavid C Somayajulu 	}
146711e25f0dSDavid C Somayajulu 
146811e25f0dSDavid C Somayajulu 	if (!ret)
146911e25f0dSDavid C Somayajulu 		ha->rx_coalesce_usecs = (uint8_t)usecs;
147011e25f0dSDavid C Somayajulu 
147111e25f0dSDavid C Somayajulu         return (err);
147211e25f0dSDavid C Somayajulu }
147311e25f0dSDavid C Somayajulu 
147411e25f0dSDavid C Somayajulu static void
qlnx_add_sp_stats_sysctls(qlnx_host_t * ha)147511e25f0dSDavid C Somayajulu qlnx_add_sp_stats_sysctls(qlnx_host_t *ha)
147611e25f0dSDavid C Somayajulu {
147711e25f0dSDavid C Somayajulu         struct sysctl_ctx_list	*ctx;
147811e25f0dSDavid C Somayajulu         struct sysctl_oid_list	*children;
147911e25f0dSDavid C Somayajulu 	struct sysctl_oid	*ctx_oid;
148011e25f0dSDavid C Somayajulu 
148111e25f0dSDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
148211e25f0dSDavid C Somayajulu 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
148311e25f0dSDavid C Somayajulu 
148411e25f0dSDavid C Somayajulu 	ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "spstat",
14857029da5cSPawel Biernacki 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "spstat");
148611e25f0dSDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
148711e25f0dSDavid C Somayajulu 
148811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
148911e25f0dSDavid C Somayajulu                 OID_AUTO, "sp_interrupts",
149011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->sp_interrupts,
149111e25f0dSDavid C Somayajulu                 "No. of slowpath interrupts");
149211e25f0dSDavid C Somayajulu 
149311e25f0dSDavid C Somayajulu 	return;
149411e25f0dSDavid C Somayajulu }
149511e25f0dSDavid C Somayajulu 
149611e25f0dSDavid C Somayajulu static void
qlnx_add_fp_stats_sysctls(qlnx_host_t * ha)149711e25f0dSDavid C Somayajulu qlnx_add_fp_stats_sysctls(qlnx_host_t *ha)
149811e25f0dSDavid C Somayajulu {
149911e25f0dSDavid C Somayajulu         struct sysctl_ctx_list	*ctx;
150011e25f0dSDavid C Somayajulu         struct sysctl_oid_list	*children;
150111e25f0dSDavid C Somayajulu         struct sysctl_oid_list	*node_children;
150211e25f0dSDavid C Somayajulu 	struct sysctl_oid	*ctx_oid;
150311e25f0dSDavid C Somayajulu 	int			i, j;
150411e25f0dSDavid C Somayajulu 	uint8_t			name_str[16];
150511e25f0dSDavid C Somayajulu 
150611e25f0dSDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
150711e25f0dSDavid C Somayajulu 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
150811e25f0dSDavid C Somayajulu 
150911e25f0dSDavid C Somayajulu 	ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "fpstat",
15107029da5cSPawel Biernacki 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "fpstat");
151111e25f0dSDavid C Somayajulu 	children = SYSCTL_CHILDREN(ctx_oid);
151211e25f0dSDavid C Somayajulu 
151311e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
151411e25f0dSDavid C Somayajulu 		bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
151511e25f0dSDavid C Somayajulu 		snprintf(name_str, sizeof(name_str), "%d", i);
151611e25f0dSDavid C Somayajulu 
151711e25f0dSDavid C Somayajulu 		ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, name_str,
15187029da5cSPawel Biernacki 		    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, name_str);
151911e25f0dSDavid C Somayajulu 		node_children = SYSCTL_CHILDREN(ctx_oid);
152011e25f0dSDavid C Somayajulu 
152111e25f0dSDavid C Somayajulu 		/* Tx Related */
152211e25f0dSDavid C Somayajulu 
152311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
152411e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_pkts_processed",
152511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_pkts_processed,
152611e25f0dSDavid C Somayajulu 			"No. of packets processed for transmission");
152711e25f0dSDavid C Somayajulu 
152811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
152911e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_pkts_freed",
153011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_pkts_freed,
153111e25f0dSDavid C Somayajulu 			"No. of freed packets");
153211e25f0dSDavid C Somayajulu 
153311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
153411e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_pkts_transmitted",
153511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_pkts_transmitted,
153611e25f0dSDavid C Somayajulu 			"No. of transmitted packets");
153711e25f0dSDavid C Somayajulu 
153811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
153911e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_pkts_completed",
154011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_pkts_completed,
154111e25f0dSDavid C Somayajulu 			"No. of transmit completions");
154211e25f0dSDavid C Somayajulu 
154311e25f0dSDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
154445f13123SDavid C Somayajulu                         OID_AUTO, "tx_non_tso_pkts",
154545f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_non_tso_pkts,
154645f13123SDavid C Somayajulu                         "No. of non LSO transmited packets");
154745f13123SDavid C Somayajulu 
154845f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
154945f13123SDavid C Somayajulu 
155045f13123SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
155145f13123SDavid C Somayajulu                         OID_AUTO, "tx_pkts_trans_ctx",
155245f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_pkts_trans_ctx,
155345f13123SDavid C Somayajulu                         "No. of transmitted packets in transmit context");
155445f13123SDavid C Somayajulu 
155545f13123SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
155645f13123SDavid C Somayajulu                         OID_AUTO, "tx_pkts_compl_ctx",
155745f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_pkts_compl_ctx,
155845f13123SDavid C Somayajulu                         "No. of transmit completions in transmit context");
155945f13123SDavid C Somayajulu 
156045f13123SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
156145f13123SDavid C Somayajulu                         OID_AUTO, "tx_pkts_trans_fp",
156245f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_pkts_trans_fp,
156345f13123SDavid C Somayajulu                         "No. of transmitted packets in taskqueue");
156445f13123SDavid C Somayajulu 
156545f13123SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
156645f13123SDavid C Somayajulu                         OID_AUTO, "tx_pkts_compl_fp",
156745f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_pkts_compl_fp,
156845f13123SDavid C Somayajulu                         "No. of transmit completions in taskqueue");
156945f13123SDavid C Somayajulu 
157045f13123SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
157145f13123SDavid C Somayajulu                         OID_AUTO, "tx_pkts_compl_intr",
157245f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_pkts_compl_intr,
157345f13123SDavid C Somayajulu                         "No. of transmit completions in interrupt ctx");
157445f13123SDavid C Somayajulu #endif
157545f13123SDavid C Somayajulu 
157645f13123SDavid C Somayajulu                 SYSCTL_ADD_QUAD(ctx, node_children,
157745f13123SDavid C Somayajulu                         OID_AUTO, "tx_tso_pkts",
157845f13123SDavid C Somayajulu                         CTLFLAG_RD, &ha->fp_array[i].tx_tso_pkts,
157945f13123SDavid C Somayajulu                         "No. of LSO transmited packets");
158045f13123SDavid C Somayajulu 
158145f13123SDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
158211e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_lso_wnd_min_len",
158311e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_lso_wnd_min_len,
158411e25f0dSDavid C Somayajulu 			"tx_lso_wnd_min_len");
158511e25f0dSDavid C Somayajulu 
158611e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
158711e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_defrag",
158811e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_defrag,
158911e25f0dSDavid C Somayajulu 			"tx_defrag");
159011e25f0dSDavid C Somayajulu 
159111e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
159211e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_nsegs_gt_elem_left",
159311e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_nsegs_gt_elem_left,
159411e25f0dSDavid C Somayajulu 			"tx_nsegs_gt_elem_left");
159511e25f0dSDavid C Somayajulu 
159611e25f0dSDavid C Somayajulu 		SYSCTL_ADD_UINT(ctx, node_children,
159711e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_tso_max_nsegs",
159811e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_tso_max_nsegs,
159911e25f0dSDavid C Somayajulu 			ha->fp_array[i].tx_tso_max_nsegs, "tx_tso_max_nsegs");
160011e25f0dSDavid C Somayajulu 
160111e25f0dSDavid C Somayajulu 		SYSCTL_ADD_UINT(ctx, node_children,
160211e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_tso_min_nsegs",
160311e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_tso_min_nsegs,
160411e25f0dSDavid C Somayajulu 			ha->fp_array[i].tx_tso_min_nsegs, "tx_tso_min_nsegs");
160511e25f0dSDavid C Somayajulu 
160611e25f0dSDavid C Somayajulu 		SYSCTL_ADD_UINT(ctx, node_children,
160711e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_tso_max_pkt_len",
160811e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_tso_max_pkt_len,
160911e25f0dSDavid C Somayajulu 			ha->fp_array[i].tx_tso_max_pkt_len,
161011e25f0dSDavid C Somayajulu 			"tx_tso_max_pkt_len");
161111e25f0dSDavid C Somayajulu 
161211e25f0dSDavid C Somayajulu 		SYSCTL_ADD_UINT(ctx, node_children,
161311e25f0dSDavid C Somayajulu 			OID_AUTO, "tx_tso_min_pkt_len",
161411e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tx_tso_min_pkt_len,
161511e25f0dSDavid C Somayajulu 			ha->fp_array[i].tx_tso_min_pkt_len,
161611e25f0dSDavid C Somayajulu 			"tx_tso_min_pkt_len");
161711e25f0dSDavid C Somayajulu 
161811e25f0dSDavid C Somayajulu 		for (j = 0; j < QLNX_FP_MAX_SEGS; j++) {
161911e25f0dSDavid C Somayajulu 			bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
162011e25f0dSDavid C Somayajulu 			snprintf(name_str, sizeof(name_str),
162111e25f0dSDavid C Somayajulu 				"tx_pkts_nseg_%02d", (j+1));
162211e25f0dSDavid C Somayajulu 
162311e25f0dSDavid C Somayajulu 			SYSCTL_ADD_QUAD(ctx, node_children,
162411e25f0dSDavid C Somayajulu 				OID_AUTO, name_str, CTLFLAG_RD,
162511e25f0dSDavid C Somayajulu 				&ha->fp_array[i].tx_pkts[j], name_str);
162611e25f0dSDavid C Somayajulu 		}
162711e25f0dSDavid C Somayajulu 
162845f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
162945f13123SDavid C Somayajulu                 for (j = 0; j < 18; j++) {
163045f13123SDavid C Somayajulu                         bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
163145f13123SDavid C Somayajulu                         snprintf(name_str, sizeof(name_str),
163245f13123SDavid C Somayajulu                                 "tx_pkts_hist_%02d", (j+1));
163345f13123SDavid C Somayajulu 
163445f13123SDavid C Somayajulu                         SYSCTL_ADD_QUAD(ctx, node_children,
163545f13123SDavid C Somayajulu                                 OID_AUTO, name_str, CTLFLAG_RD,
163645f13123SDavid C Somayajulu                                 &ha->fp_array[i].tx_pkts_hist[j], name_str);
163745f13123SDavid C Somayajulu                 }
163845f13123SDavid C Somayajulu                 for (j = 0; j < 5; j++) {
163945f13123SDavid C Somayajulu                         bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
164045f13123SDavid C Somayajulu                         snprintf(name_str, sizeof(name_str),
164145f13123SDavid C Somayajulu                                 "tx_comInt_%02d", (j+1));
164245f13123SDavid C Somayajulu 
164345f13123SDavid C Somayajulu                         SYSCTL_ADD_QUAD(ctx, node_children,
164445f13123SDavid C Somayajulu                                 OID_AUTO, name_str, CTLFLAG_RD,
164545f13123SDavid C Somayajulu                                 &ha->fp_array[i].tx_comInt[j], name_str);
164645f13123SDavid C Somayajulu                 }
164745f13123SDavid C Somayajulu                 for (j = 0; j < 18; j++) {
164845f13123SDavid C Somayajulu                         bzero(name_str, (sizeof(uint8_t) * sizeof(name_str)));
164945f13123SDavid C Somayajulu                         snprintf(name_str, sizeof(name_str),
165045f13123SDavid C Somayajulu                                 "tx_pkts_q_%02d", (j+1));
165145f13123SDavid C Somayajulu 
165245f13123SDavid C Somayajulu                         SYSCTL_ADD_QUAD(ctx, node_children,
165345f13123SDavid C Somayajulu                                 OID_AUTO, name_str, CTLFLAG_RD,
165445f13123SDavid C Somayajulu                                 &ha->fp_array[i].tx_pkts_q[j], name_str);
165545f13123SDavid C Somayajulu                 }
165645f13123SDavid C Somayajulu #endif
165745f13123SDavid C Somayajulu 
165811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
165911e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_nsegs_gt_elem_left",
166011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_nsegs_gt_elem_left,
166111e25f0dSDavid C Somayajulu 			"err_tx_nsegs_gt_elem_left");
166211e25f0dSDavid C Somayajulu 
166311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
166411e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_dmamap_create",
166511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_dmamap_create,
166611e25f0dSDavid C Somayajulu 			"err_tx_dmamap_create");
166711e25f0dSDavid C Somayajulu 
166811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
166911e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_defrag_dmamap_load",
167011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_defrag_dmamap_load,
167111e25f0dSDavid C Somayajulu 			"err_tx_defrag_dmamap_load");
167211e25f0dSDavid C Somayajulu 
167311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
167411e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_non_tso_max_seg",
167511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_non_tso_max_seg,
167611e25f0dSDavid C Somayajulu 			"err_tx_non_tso_max_seg");
167711e25f0dSDavid C Somayajulu 
167811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
167911e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_dmamap_load",
168011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_dmamap_load,
168111e25f0dSDavid C Somayajulu 			"err_tx_dmamap_load");
168211e25f0dSDavid C Somayajulu 
168311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
168411e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_defrag",
168511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_defrag,
168611e25f0dSDavid C Somayajulu 			"err_tx_defrag");
168711e25f0dSDavid C Somayajulu 
168811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
168911e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_free_pkt_null",
169011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_free_pkt_null,
169111e25f0dSDavid C Somayajulu 			"err_tx_free_pkt_null");
169211e25f0dSDavid C Somayajulu 
169311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
169411e25f0dSDavid C Somayajulu 			OID_AUTO, "err_tx_cons_idx_conflict",
169511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_tx_cons_idx_conflict,
169611e25f0dSDavid C Somayajulu 			"err_tx_cons_idx_conflict");
169711e25f0dSDavid C Somayajulu 
169811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
169911e25f0dSDavid C Somayajulu 			OID_AUTO, "lro_cnt_64",
170011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_64,
170111e25f0dSDavid C Somayajulu 			"lro_cnt_64");
170211e25f0dSDavid C Somayajulu 
170311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
170411e25f0dSDavid C Somayajulu 			OID_AUTO, "lro_cnt_128",
170511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_128,
170611e25f0dSDavid C Somayajulu 			"lro_cnt_128");
170711e25f0dSDavid C Somayajulu 
170811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
170911e25f0dSDavid C Somayajulu 			OID_AUTO, "lro_cnt_256",
171011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_256,
171111e25f0dSDavid C Somayajulu 			"lro_cnt_256");
171211e25f0dSDavid C Somayajulu 
171311e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
171411e25f0dSDavid C Somayajulu 			OID_AUTO, "lro_cnt_512",
171511e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_512,
171611e25f0dSDavid C Somayajulu 			"lro_cnt_512");
171711e25f0dSDavid C Somayajulu 
171811e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
171911e25f0dSDavid C Somayajulu 			OID_AUTO, "lro_cnt_1024",
172011e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].lro_cnt_1024,
172111e25f0dSDavid C Somayajulu 			"lro_cnt_1024");
172211e25f0dSDavid C Somayajulu 
172311e25f0dSDavid C Somayajulu 		/* Rx Related */
172411e25f0dSDavid C Somayajulu 
172511e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
172611e25f0dSDavid C Somayajulu 			OID_AUTO, "rx_pkts",
172711e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].rx_pkts,
172811e25f0dSDavid C Somayajulu 			"No. of received packets");
172911e25f0dSDavid C Somayajulu 
173011e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
173111e25f0dSDavid C Somayajulu 			OID_AUTO, "tpa_start",
173211e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tpa_start,
173311e25f0dSDavid C Somayajulu 			"No. of tpa_start packets");
173411e25f0dSDavid C Somayajulu 
173511e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
173611e25f0dSDavid C Somayajulu 			OID_AUTO, "tpa_cont",
173711e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tpa_cont,
173811e25f0dSDavid C Somayajulu 			"No. of tpa_cont packets");
173911e25f0dSDavid C Somayajulu 
174011e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
174111e25f0dSDavid C Somayajulu 			OID_AUTO, "tpa_end",
174211e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].tpa_end,
174311e25f0dSDavid C Somayajulu 			"No. of tpa_end packets");
174411e25f0dSDavid C Somayajulu 
174511e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
174611e25f0dSDavid C Somayajulu 			OID_AUTO, "err_m_getcl",
174711e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_m_getcl,
174811e25f0dSDavid C Somayajulu 			"err_m_getcl");
174911e25f0dSDavid C Somayajulu 
175011e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
175111e25f0dSDavid C Somayajulu 			OID_AUTO, "err_m_getjcl",
175211e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_m_getjcl,
175311e25f0dSDavid C Somayajulu 			"err_m_getjcl");
175411e25f0dSDavid C Somayajulu 
175511e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
175611e25f0dSDavid C Somayajulu 			OID_AUTO, "err_rx_hw_errors",
175711e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_rx_hw_errors,
175811e25f0dSDavid C Somayajulu 			"err_rx_hw_errors");
175911e25f0dSDavid C Somayajulu 
176011e25f0dSDavid C Somayajulu 		SYSCTL_ADD_QUAD(ctx, node_children,
176111e25f0dSDavid C Somayajulu 			OID_AUTO, "err_rx_alloc_errors",
176211e25f0dSDavid C Somayajulu 			CTLFLAG_RD, &ha->fp_array[i].err_rx_alloc_errors,
176311e25f0dSDavid C Somayajulu 			"err_rx_alloc_errors");
176411e25f0dSDavid C Somayajulu 	}
176511e25f0dSDavid C Somayajulu 
176611e25f0dSDavid C Somayajulu 	return;
176711e25f0dSDavid C Somayajulu }
176811e25f0dSDavid C Somayajulu 
176911e25f0dSDavid C Somayajulu static void
qlnx_add_hw_stats_sysctls(qlnx_host_t * ha)177011e25f0dSDavid C Somayajulu qlnx_add_hw_stats_sysctls(qlnx_host_t *ha)
177111e25f0dSDavid C Somayajulu {
177211e25f0dSDavid C Somayajulu         struct sysctl_ctx_list	*ctx;
177311e25f0dSDavid C Somayajulu         struct sysctl_oid_list	*children;
177411e25f0dSDavid C Somayajulu 	struct sysctl_oid	*ctx_oid;
177511e25f0dSDavid C Somayajulu 
177611e25f0dSDavid C Somayajulu         ctx = device_get_sysctl_ctx(ha->pci_dev);
177711e25f0dSDavid C Somayajulu 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(ha->pci_dev));
177811e25f0dSDavid C Somayajulu 
177911e25f0dSDavid C Somayajulu 	ctx_oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "hwstat",
17807029da5cSPawel Biernacki 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "hwstat");
178111e25f0dSDavid C Somayajulu         children = SYSCTL_CHILDREN(ctx_oid);
178211e25f0dSDavid C Somayajulu 
178311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
178411e25f0dSDavid C Somayajulu                 OID_AUTO, "no_buff_discards",
178511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.no_buff_discards,
178611e25f0dSDavid C Somayajulu                 "No. of packets discarded due to lack of buffer");
178711e25f0dSDavid C Somayajulu 
178811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
178911e25f0dSDavid C Somayajulu                 OID_AUTO, "packet_too_big_discard",
179011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.packet_too_big_discard,
179111e25f0dSDavid C Somayajulu                 "No. of packets discarded because packet was too big");
179211e25f0dSDavid C Somayajulu 
179311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
179411e25f0dSDavid C Somayajulu                 OID_AUTO, "ttl0_discard",
179511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.ttl0_discard,
179611e25f0dSDavid C Somayajulu                 "ttl0_discard");
179711e25f0dSDavid C Somayajulu 
179811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
179911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_ucast_bytes",
180011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_ucast_bytes,
180111e25f0dSDavid C Somayajulu                 "rx_ucast_bytes");
180211e25f0dSDavid C Somayajulu 
180311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
180411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mcast_bytes",
180511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mcast_bytes,
180611e25f0dSDavid C Somayajulu                 "rx_mcast_bytes");
180711e25f0dSDavid C Somayajulu 
180811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
180911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_bcast_bytes",
181011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_bcast_bytes,
181111e25f0dSDavid C Somayajulu                 "rx_bcast_bytes");
181211e25f0dSDavid C Somayajulu 
181311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
181411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_ucast_pkts",
181511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_ucast_pkts,
181611e25f0dSDavid C Somayajulu                 "rx_ucast_pkts");
181711e25f0dSDavid C Somayajulu 
181811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
181911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mcast_pkts",
182011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mcast_pkts,
182111e25f0dSDavid C Somayajulu                 "rx_mcast_pkts");
182211e25f0dSDavid C Somayajulu 
182311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
182411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_bcast_pkts",
182511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_bcast_pkts,
182611e25f0dSDavid C Somayajulu                 "rx_bcast_pkts");
182711e25f0dSDavid C Somayajulu 
182811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
182911e25f0dSDavid C Somayajulu                 OID_AUTO, "mftag_filter_discards",
183011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.mftag_filter_discards,
183111e25f0dSDavid C Somayajulu                 "mftag_filter_discards");
183211e25f0dSDavid C Somayajulu 
183311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
183411e25f0dSDavid C Somayajulu                 OID_AUTO, "mac_filter_discards",
183511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.mac_filter_discards,
183611e25f0dSDavid C Somayajulu                 "mac_filter_discards");
183711e25f0dSDavid C Somayajulu 
183811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
183911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_ucast_bytes",
184011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_ucast_bytes,
184111e25f0dSDavid C Somayajulu                 "tx_ucast_bytes");
184211e25f0dSDavid C Somayajulu 
184311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
184411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mcast_bytes",
184511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mcast_bytes,
184611e25f0dSDavid C Somayajulu                 "tx_mcast_bytes");
184711e25f0dSDavid C Somayajulu 
184811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
184911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_bcast_bytes",
185011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_bcast_bytes,
185111e25f0dSDavid C Somayajulu                 "tx_bcast_bytes");
185211e25f0dSDavid C Somayajulu 
185311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
185411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_ucast_pkts",
185511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_ucast_pkts,
185611e25f0dSDavid C Somayajulu                 "tx_ucast_pkts");
185711e25f0dSDavid C Somayajulu 
185811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
185911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mcast_pkts",
186011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mcast_pkts,
186111e25f0dSDavid C Somayajulu                 "tx_mcast_pkts");
186211e25f0dSDavid C Somayajulu 
186311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
186411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_bcast_pkts",
186511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_bcast_pkts,
186611e25f0dSDavid C Somayajulu                 "tx_bcast_pkts");
186711e25f0dSDavid C Somayajulu 
186811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
186911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_err_drop_pkts",
187011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_err_drop_pkts,
187111e25f0dSDavid C Somayajulu                 "tx_err_drop_pkts");
187211e25f0dSDavid C Somayajulu 
187311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
187411e25f0dSDavid C Somayajulu                 OID_AUTO, "tpa_coalesced_pkts",
187511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tpa_coalesced_pkts,
187611e25f0dSDavid C Somayajulu                 "tpa_coalesced_pkts");
187711e25f0dSDavid C Somayajulu 
187811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
187911e25f0dSDavid C Somayajulu                 OID_AUTO, "tpa_coalesced_events",
188011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tpa_coalesced_events,
188111e25f0dSDavid C Somayajulu                 "tpa_coalesced_events");
188211e25f0dSDavid C Somayajulu 
188311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
188411e25f0dSDavid C Somayajulu                 OID_AUTO, "tpa_aborts_num",
188511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tpa_aborts_num,
188611e25f0dSDavid C Somayajulu                 "tpa_aborts_num");
188711e25f0dSDavid C Somayajulu 
188811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
188911e25f0dSDavid C Somayajulu                 OID_AUTO, "tpa_not_coalesced_pkts",
189011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tpa_not_coalesced_pkts,
189111e25f0dSDavid C Somayajulu                 "tpa_not_coalesced_pkts");
189211e25f0dSDavid C Somayajulu 
189311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
189411e25f0dSDavid C Somayajulu                 OID_AUTO, "tpa_coalesced_bytes",
189511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tpa_coalesced_bytes,
189611e25f0dSDavid C Somayajulu                 "tpa_coalesced_bytes");
189711e25f0dSDavid C Somayajulu 
189811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
189911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_64_byte_packets",
190011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_64_byte_packets,
190111e25f0dSDavid C Somayajulu                 "rx_64_byte_packets");
190211e25f0dSDavid C Somayajulu 
190311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
190411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_65_to_127_byte_packets",
190511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_65_to_127_byte_packets,
190611e25f0dSDavid C Somayajulu                 "rx_65_to_127_byte_packets");
190711e25f0dSDavid C Somayajulu 
190811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
190911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_128_to_255_byte_packets",
191011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_128_to_255_byte_packets,
191111e25f0dSDavid C Somayajulu                 "rx_128_to_255_byte_packets");
191211e25f0dSDavid C Somayajulu 
191311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
191411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_256_to_511_byte_packets",
191511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_256_to_511_byte_packets,
191611e25f0dSDavid C Somayajulu                 "rx_256_to_511_byte_packets");
191711e25f0dSDavid C Somayajulu 
191811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
191911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_512_to_1023_byte_packets",
192011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_512_to_1023_byte_packets,
192111e25f0dSDavid C Somayajulu                 "rx_512_to_1023_byte_packets");
192211e25f0dSDavid C Somayajulu 
192311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
192411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_1024_to_1518_byte_packets",
192511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_1024_to_1518_byte_packets,
192611e25f0dSDavid C Somayajulu                 "rx_1024_to_1518_byte_packets");
192711e25f0dSDavid C Somayajulu 
192811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
192911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_1519_to_1522_byte_packets",
193011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.rx_1519_to_1522_byte_packets,
193111e25f0dSDavid C Somayajulu                 "rx_1519_to_1522_byte_packets");
193211e25f0dSDavid C Somayajulu 
193311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
193411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_1523_to_2047_byte_packets",
193511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.rx_1519_to_2047_byte_packets,
193611e25f0dSDavid C Somayajulu                 "rx_1523_to_2047_byte_packets");
193711e25f0dSDavid C Somayajulu 
193811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
193911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_2048_to_4095_byte_packets",
194011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.rx_2048_to_4095_byte_packets,
194111e25f0dSDavid C Somayajulu                 "rx_2048_to_4095_byte_packets");
194211e25f0dSDavid C Somayajulu 
194311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
194411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_4096_to_9216_byte_packets",
194511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.rx_4096_to_9216_byte_packets,
194611e25f0dSDavid C Somayajulu                 "rx_4096_to_9216_byte_packets");
194711e25f0dSDavid C Somayajulu 
194811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
194911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_9217_to_16383_byte_packets",
195011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.rx_9217_to_16383_byte_packets,
195111e25f0dSDavid C Somayajulu                 "rx_9217_to_16383_byte_packets");
195211e25f0dSDavid C Somayajulu 
195311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
195411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_crc_errors",
195511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_crc_errors,
195611e25f0dSDavid C Somayajulu                 "rx_crc_errors");
195711e25f0dSDavid C Somayajulu 
195811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
195911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mac_crtl_frames",
196011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mac_crtl_frames,
196111e25f0dSDavid C Somayajulu                 "rx_mac_crtl_frames");
196211e25f0dSDavid C Somayajulu 
196311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
196411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_pause_frames",
196511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_pause_frames,
196611e25f0dSDavid C Somayajulu                 "rx_pause_frames");
196711e25f0dSDavid C Somayajulu 
196811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
196911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_pfc_frames",
197011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_pfc_frames,
197111e25f0dSDavid C Somayajulu                 "rx_pfc_frames");
197211e25f0dSDavid C Somayajulu 
197311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
197411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_align_errors",
197511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_align_errors,
197611e25f0dSDavid C Somayajulu                 "rx_align_errors");
197711e25f0dSDavid C Somayajulu 
197811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
197911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_carrier_errors",
198011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_carrier_errors,
198111e25f0dSDavid C Somayajulu                 "rx_carrier_errors");
198211e25f0dSDavid C Somayajulu 
198311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
198411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_oversize_packets",
198511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_oversize_packets,
198611e25f0dSDavid C Somayajulu                 "rx_oversize_packets");
198711e25f0dSDavid C Somayajulu 
198811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
198911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_jabbers",
199011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_jabbers,
199111e25f0dSDavid C Somayajulu                 "rx_jabbers");
199211e25f0dSDavid C Somayajulu 
199311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
199411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_undersize_packets",
199511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_undersize_packets,
199611e25f0dSDavid C Somayajulu                 "rx_undersize_packets");
199711e25f0dSDavid C Somayajulu 
199811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
199911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_fragments",
200011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_fragments,
200111e25f0dSDavid C Somayajulu                 "rx_fragments");
200211e25f0dSDavid C Somayajulu 
200311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
200411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_64_byte_packets",
200511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_64_byte_packets,
200611e25f0dSDavid C Somayajulu                 "tx_64_byte_packets");
200711e25f0dSDavid C Somayajulu 
200811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
200911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_65_to_127_byte_packets",
201011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_65_to_127_byte_packets,
201111e25f0dSDavid C Somayajulu                 "tx_65_to_127_byte_packets");
201211e25f0dSDavid C Somayajulu 
201311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
201411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_128_to_255_byte_packets",
201511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_128_to_255_byte_packets,
201611e25f0dSDavid C Somayajulu                 "tx_128_to_255_byte_packets");
201711e25f0dSDavid C Somayajulu 
201811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
201911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_256_to_511_byte_packets",
202011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_256_to_511_byte_packets,
202111e25f0dSDavid C Somayajulu                 "tx_256_to_511_byte_packets");
202211e25f0dSDavid C Somayajulu 
202311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
202411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_512_to_1023_byte_packets",
202511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_512_to_1023_byte_packets,
202611e25f0dSDavid C Somayajulu                 "tx_512_to_1023_byte_packets");
202711e25f0dSDavid C Somayajulu 
202811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
202911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_1024_to_1518_byte_packets",
203011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_1024_to_1518_byte_packets,
203111e25f0dSDavid C Somayajulu                 "tx_1024_to_1518_byte_packets");
203211e25f0dSDavid C Somayajulu 
203311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
203411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_1519_to_2047_byte_packets",
203511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.tx_1519_to_2047_byte_packets,
203611e25f0dSDavid C Somayajulu                 "tx_1519_to_2047_byte_packets");
203711e25f0dSDavid C Somayajulu 
203811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
203911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_2048_to_4095_byte_packets",
204011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.tx_2048_to_4095_byte_packets,
204111e25f0dSDavid C Somayajulu                 "tx_2048_to_4095_byte_packets");
204211e25f0dSDavid C Somayajulu 
204311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
204411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_4096_to_9216_byte_packets",
204511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.tx_4096_to_9216_byte_packets,
204611e25f0dSDavid C Somayajulu                 "tx_4096_to_9216_byte_packets");
204711e25f0dSDavid C Somayajulu 
204811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
204911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_9217_to_16383_byte_packets",
205011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.tx_9217_to_16383_byte_packets,
205111e25f0dSDavid C Somayajulu                 "tx_9217_to_16383_byte_packets");
205211e25f0dSDavid C Somayajulu 
205311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
205411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_pause_frames",
205511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_pause_frames,
205611e25f0dSDavid C Somayajulu                 "tx_pause_frames");
205711e25f0dSDavid C Somayajulu 
205811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
205911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_pfc_frames",
206011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_pfc_frames,
206111e25f0dSDavid C Somayajulu                 "tx_pfc_frames");
206211e25f0dSDavid C Somayajulu 
206311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
206411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_lpi_entry_count",
206511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.tx_lpi_entry_count,
206611e25f0dSDavid C Somayajulu                 "tx_lpi_entry_count");
206711e25f0dSDavid C Somayajulu 
206811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
206911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_total_collisions",
207011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.bb.tx_total_collisions,
207111e25f0dSDavid C Somayajulu                 "tx_total_collisions");
207211e25f0dSDavid C Somayajulu 
207311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
207411e25f0dSDavid C Somayajulu                 OID_AUTO, "brb_truncates",
207511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.brb_truncates,
207611e25f0dSDavid C Somayajulu                 "brb_truncates");
207711e25f0dSDavid C Somayajulu 
207811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
207911e25f0dSDavid C Somayajulu                 OID_AUTO, "brb_discards",
208011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.brb_discards,
208111e25f0dSDavid C Somayajulu                 "brb_discards");
208211e25f0dSDavid C Somayajulu 
208311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
208411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mac_bytes",
208511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mac_bytes,
208611e25f0dSDavid C Somayajulu                 "rx_mac_bytes");
208711e25f0dSDavid C Somayajulu 
208811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
208911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mac_uc_packets",
209011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mac_uc_packets,
209111e25f0dSDavid C Somayajulu                 "rx_mac_uc_packets");
209211e25f0dSDavid C Somayajulu 
209311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
209411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mac_mc_packets",
209511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mac_mc_packets,
209611e25f0dSDavid C Somayajulu                 "rx_mac_mc_packets");
209711e25f0dSDavid C Somayajulu 
209811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
209911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mac_bc_packets",
210011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mac_bc_packets,
210111e25f0dSDavid C Somayajulu                 "rx_mac_bc_packets");
210211e25f0dSDavid C Somayajulu 
210311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
210411e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_mac_frames_ok",
210511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.rx_mac_frames_ok,
210611e25f0dSDavid C Somayajulu                 "rx_mac_frames_ok");
210711e25f0dSDavid C Somayajulu 
210811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
210911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mac_bytes",
211011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mac_bytes,
211111e25f0dSDavid C Somayajulu                 "tx_mac_bytes");
211211e25f0dSDavid C Somayajulu 
211311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
211411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mac_uc_packets",
211511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mac_uc_packets,
211611e25f0dSDavid C Somayajulu                 "tx_mac_uc_packets");
211711e25f0dSDavid C Somayajulu 
211811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
211911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mac_mc_packets",
212011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mac_mc_packets,
212111e25f0dSDavid C Somayajulu                 "tx_mac_mc_packets");
212211e25f0dSDavid C Somayajulu 
212311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
212411e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mac_bc_packets",
212511e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mac_bc_packets,
212611e25f0dSDavid C Somayajulu                 "tx_mac_bc_packets");
212711e25f0dSDavid C Somayajulu 
212811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
212911e25f0dSDavid C Somayajulu                 OID_AUTO, "tx_mac_ctrl_frames",
213011e25f0dSDavid C Somayajulu                 CTLFLAG_RD, &ha->hw_stats.common.tx_mac_ctrl_frames,
213111e25f0dSDavid C Somayajulu                 "tx_mac_ctrl_frames");
213211e25f0dSDavid C Somayajulu 	return;
213311e25f0dSDavid C Somayajulu }
213411e25f0dSDavid C Somayajulu 
213511e25f0dSDavid C Somayajulu static void
qlnx_add_sysctls(qlnx_host_t * ha)213611e25f0dSDavid C Somayajulu qlnx_add_sysctls(qlnx_host_t *ha)
213711e25f0dSDavid C Somayajulu {
213811e25f0dSDavid C Somayajulu         device_t		dev = ha->pci_dev;
213911e25f0dSDavid C Somayajulu 	struct sysctl_ctx_list	*ctx;
214011e25f0dSDavid C Somayajulu 	struct sysctl_oid_list	*children;
214111e25f0dSDavid C Somayajulu 
214211e25f0dSDavid C Somayajulu 	ctx = device_get_sysctl_ctx(dev);
214311e25f0dSDavid C Somayajulu 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
214411e25f0dSDavid C Somayajulu 
214511e25f0dSDavid C Somayajulu 	qlnx_add_fp_stats_sysctls(ha);
214611e25f0dSDavid C Somayajulu 	qlnx_add_sp_stats_sysctls(ha);
2147217ec208SDavid C Somayajulu 
2148217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0)
214911e25f0dSDavid C Somayajulu 		qlnx_add_hw_stats_sysctls(ha);
215011e25f0dSDavid C Somayajulu 
215111e25f0dSDavid C Somayajulu 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "Driver_Version",
215211e25f0dSDavid C Somayajulu 		CTLFLAG_RD, qlnx_ver_str, 0,
215311e25f0dSDavid C Somayajulu 		"Driver Version");
215411e25f0dSDavid C Somayajulu 
215511e25f0dSDavid C Somayajulu 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "STORMFW_Version",
215611e25f0dSDavid C Somayajulu 		CTLFLAG_RD, ha->stormfw_ver, 0,
215711e25f0dSDavid C Somayajulu 		"STORM Firmware Version");
215811e25f0dSDavid C Somayajulu 
215911e25f0dSDavid C Somayajulu 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "MFW_Version",
216011e25f0dSDavid C Somayajulu 		CTLFLAG_RD, ha->mfw_ver, 0,
216111e25f0dSDavid C Somayajulu 		"Management Firmware Version");
216211e25f0dSDavid C Somayajulu 
216311e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
216411e25f0dSDavid C Somayajulu                 OID_AUTO, "personality", CTLFLAG_RD,
216511e25f0dSDavid C Somayajulu                 &ha->personality, ha->personality,
216611e25f0dSDavid C Somayajulu 		"\tpersonality = 0 => Ethernet Only\n"
216711e25f0dSDavid C Somayajulu 		"\tpersonality = 3 => Ethernet and RoCE\n"
216811e25f0dSDavid C Somayajulu 		"\tpersonality = 4 => Ethernet and iWARP\n"
216911e25f0dSDavid C Somayajulu 		"\tpersonality = 6 => Default in Shared Memory\n");
217011e25f0dSDavid C Somayajulu 
217111e25f0dSDavid C Somayajulu         ha->dbg_level = 0;
217211e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
217311e25f0dSDavid C Somayajulu                 OID_AUTO, "debug", CTLFLAG_RW,
217411e25f0dSDavid C Somayajulu                 &ha->dbg_level, ha->dbg_level, "Debug Level");
217511e25f0dSDavid C Somayajulu 
21767a377fbeSDavid C Somayajulu         ha->dp_level = 0x01;
217711e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
217811e25f0dSDavid C Somayajulu                 OID_AUTO, "dp_level", CTLFLAG_RW,
217911e25f0dSDavid C Somayajulu                 &ha->dp_level, ha->dp_level, "DP Level");
218011e25f0dSDavid C Somayajulu 
218177388ed2SDavid C Somayajulu         ha->dbg_trace_lro_cnt = 0;
218277388ed2SDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
218377388ed2SDavid C Somayajulu                 OID_AUTO, "dbg_trace_lro_cnt", CTLFLAG_RW,
218477388ed2SDavid C Somayajulu                 &ha->dbg_trace_lro_cnt, ha->dbg_trace_lro_cnt,
218577388ed2SDavid C Somayajulu 		"Trace LRO Counts");
218677388ed2SDavid C Somayajulu 
218777388ed2SDavid C Somayajulu         ha->dbg_trace_tso_pkt_len = 0;
218877388ed2SDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
218977388ed2SDavid C Somayajulu                 OID_AUTO, "dbg_trace_tso_pkt_len", CTLFLAG_RW,
219077388ed2SDavid C Somayajulu                 &ha->dbg_trace_tso_pkt_len, ha->dbg_trace_tso_pkt_len,
219177388ed2SDavid C Somayajulu 		"Trace TSO packet lengths");
219277388ed2SDavid C Somayajulu 
219311e25f0dSDavid C Somayajulu         ha->dp_module = 0;
219411e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
219511e25f0dSDavid C Somayajulu                 OID_AUTO, "dp_module", CTLFLAG_RW,
219611e25f0dSDavid C Somayajulu                 &ha->dp_module, ha->dp_module, "DP Module");
219711e25f0dSDavid C Somayajulu 
219811e25f0dSDavid C Somayajulu         ha->err_inject = 0;
219911e25f0dSDavid C Somayajulu 
220011e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
220111e25f0dSDavid C Somayajulu                 OID_AUTO, "err_inject", CTLFLAG_RW,
220211e25f0dSDavid C Somayajulu                 &ha->err_inject, ha->err_inject, "Error Inject");
220311e25f0dSDavid C Somayajulu 
220411e25f0dSDavid C Somayajulu 	ha->storm_stats_enable = 0;
220511e25f0dSDavid C Somayajulu 
220611e25f0dSDavid C Somayajulu 	SYSCTL_ADD_UINT(ctx, children,
220711e25f0dSDavid C Somayajulu 		OID_AUTO, "storm_stats_enable", CTLFLAG_RW,
220811e25f0dSDavid C Somayajulu 		&ha->storm_stats_enable, ha->storm_stats_enable,
220911e25f0dSDavid C Somayajulu 		"Enable Storm Statistics Gathering");
221011e25f0dSDavid C Somayajulu 
221111e25f0dSDavid C Somayajulu 	ha->storm_stats_index = 0;
221211e25f0dSDavid C Somayajulu 
221311e25f0dSDavid C Somayajulu 	SYSCTL_ADD_UINT(ctx, children,
221411e25f0dSDavid C Somayajulu 		OID_AUTO, "storm_stats_index", CTLFLAG_RD,
221511e25f0dSDavid C Somayajulu 		&ha->storm_stats_index, ha->storm_stats_index,
221611e25f0dSDavid C Somayajulu 		"Enable Storm Statistics Gathering Current Index");
221711e25f0dSDavid C Somayajulu 
221811e25f0dSDavid C Somayajulu 	ha->grcdump_taken = 0;
221911e25f0dSDavid C Somayajulu 	SYSCTL_ADD_UINT(ctx, children,
222011e25f0dSDavid C Somayajulu 		OID_AUTO, "grcdump_taken", CTLFLAG_RD,
2221217ec208SDavid C Somayajulu 		&ha->grcdump_taken, ha->grcdump_taken,
2222217ec208SDavid C Somayajulu 		"grcdump_taken");
222311e25f0dSDavid C Somayajulu 
222411e25f0dSDavid C Somayajulu 	ha->idle_chk_taken = 0;
222511e25f0dSDavid C Somayajulu 	SYSCTL_ADD_UINT(ctx, children,
222611e25f0dSDavid C Somayajulu 		OID_AUTO, "idle_chk_taken", CTLFLAG_RD,
2227217ec208SDavid C Somayajulu 		&ha->idle_chk_taken, ha->idle_chk_taken,
2228217ec208SDavid C Somayajulu 		"idle_chk_taken");
222911e25f0dSDavid C Somayajulu 
223011e25f0dSDavid C Somayajulu 	SYSCTL_ADD_UINT(ctx, children,
223111e25f0dSDavid C Somayajulu 		OID_AUTO, "rx_coalesce_usecs", CTLFLAG_RD,
223211e25f0dSDavid C Somayajulu 		&ha->rx_coalesce_usecs, ha->rx_coalesce_usecs,
223311e25f0dSDavid C Somayajulu 		"rx_coalesce_usecs");
223411e25f0dSDavid C Somayajulu 
223511e25f0dSDavid C Somayajulu 	SYSCTL_ADD_UINT(ctx, children,
223611e25f0dSDavid C Somayajulu 		OID_AUTO, "tx_coalesce_usecs", CTLFLAG_RD,
223711e25f0dSDavid C Somayajulu 		&ha->tx_coalesce_usecs, ha->tx_coalesce_usecs,
223811e25f0dSDavid C Somayajulu 		"tx_coalesce_usecs");
223911e25f0dSDavid C Somayajulu 
2240217ec208SDavid C Somayajulu 	SYSCTL_ADD_PROC(ctx, children,
22417029da5cSPawel Biernacki 	    OID_AUTO, "trigger_dump",
22427029da5cSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
22437029da5cSPawel Biernacki 	    (void *)ha, 0, qlnx_trigger_dump_sysctl, "I", "trigger_dump");
2244217ec208SDavid C Somayajulu 
2245217ec208SDavid C Somayajulu 	SYSCTL_ADD_PROC(ctx, children,
2246217ec208SDavid C Somayajulu 	    OID_AUTO, "set_rx_coalesce_usecs",
22477029da5cSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
22487029da5cSPawel Biernacki 	    (void *)ha, 0, qlnx_set_rx_coalesce, "I",
2249217ec208SDavid C Somayajulu 	    "rx interrupt coalesce period microseconds");
2250217ec208SDavid C Somayajulu 
2251217ec208SDavid C Somayajulu 	SYSCTL_ADD_PROC(ctx, children,
2252217ec208SDavid C Somayajulu 	    OID_AUTO, "set_tx_coalesce_usecs",
22537029da5cSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
22547029da5cSPawel Biernacki 	    (void *)ha, 0, qlnx_set_tx_coalesce, "I",
2255217ec208SDavid C Somayajulu 	    "tx interrupt coalesce period microseconds");
2256217ec208SDavid C Somayajulu 
225777388ed2SDavid C Somayajulu 	ha->rx_pkt_threshold = 128;
225811e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
225911e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_pkt_threshold", CTLFLAG_RW,
226011e25f0dSDavid C Somayajulu                 &ha->rx_pkt_threshold, ha->rx_pkt_threshold,
226111e25f0dSDavid C Somayajulu 		"No. of Rx Pkts to process at a time");
226211e25f0dSDavid C Somayajulu 
226311e25f0dSDavid C Somayajulu 	ha->rx_jumbo_buf_eq_mtu = 0;
226411e25f0dSDavid C Somayajulu         SYSCTL_ADD_UINT(ctx, children,
226511e25f0dSDavid C Somayajulu                 OID_AUTO, "rx_jumbo_buf_eq_mtu", CTLFLAG_RW,
226611e25f0dSDavid C Somayajulu                 &ha->rx_jumbo_buf_eq_mtu, ha->rx_jumbo_buf_eq_mtu,
226711e25f0dSDavid C Somayajulu 		"== 0 => Rx Jumbo buffers are capped to 4Kbytes\n"
226811e25f0dSDavid C Somayajulu 		"otherwise Rx Jumbo buffers are set to >= MTU size\n");
226911e25f0dSDavid C Somayajulu 
227011e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
227111e25f0dSDavid C Somayajulu                 OID_AUTO, "err_illegal_intr", CTLFLAG_RD,
227211e25f0dSDavid C Somayajulu 		&ha->err_illegal_intr, "err_illegal_intr");
227311e25f0dSDavid C Somayajulu 
227411e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
227511e25f0dSDavid C Somayajulu                 OID_AUTO, "err_fp_null", CTLFLAG_RD,
227611e25f0dSDavid C Somayajulu 		&ha->err_fp_null, "err_fp_null");
227711e25f0dSDavid C Somayajulu 
227811e25f0dSDavid C Somayajulu 	SYSCTL_ADD_QUAD(ctx, children,
227911e25f0dSDavid C Somayajulu                 OID_AUTO, "err_get_proto_invalid_type", CTLFLAG_RD,
228011e25f0dSDavid C Somayajulu 		&ha->err_get_proto_invalid_type, "err_get_proto_invalid_type");
228111e25f0dSDavid C Somayajulu 	return;
228211e25f0dSDavid C Somayajulu }
228311e25f0dSDavid C Somayajulu 
228411e25f0dSDavid C Somayajulu /*****************************************************************************
228511e25f0dSDavid C Somayajulu  * Operating System Network Interface Functions
228611e25f0dSDavid C Somayajulu  *****************************************************************************/
228711e25f0dSDavid C Somayajulu 
228811e25f0dSDavid C Somayajulu static void
qlnx_init_ifnet(device_t dev,qlnx_host_t * ha)228911e25f0dSDavid C Somayajulu qlnx_init_ifnet(device_t dev, qlnx_host_t *ha)
229011e25f0dSDavid C Somayajulu {
229111e25f0dSDavid C Somayajulu 	uint16_t	device_id;
2292727bfe38SJustin Hibbits         if_t		ifp;
229311e25f0dSDavid C Somayajulu 
229411e25f0dSDavid C Somayajulu         ifp = ha->ifp = if_alloc(IFT_ETHER);
229511e25f0dSDavid C Somayajulu         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
229611e25f0dSDavid C Somayajulu 
229711e25f0dSDavid C Somayajulu 	device_id = pci_get_device(ha->pci_dev);
229811e25f0dSDavid C Somayajulu 
229911e25f0dSDavid C Somayajulu         if (device_id == QLOGIC_PCI_DEVICE_ID_1634)
2300727bfe38SJustin Hibbits 		if_setbaudrate(ifp, IF_Gbps(40));
23019efd0ba7SDavid C Somayajulu         else if ((device_id == QLOGIC_PCI_DEVICE_ID_1656) ||
23029efd0ba7SDavid C Somayajulu 			(device_id == QLOGIC_PCI_DEVICE_ID_8070))
2303727bfe38SJustin Hibbits 		if_setbaudrate(ifp, IF_Gbps(25));
230411e25f0dSDavid C Somayajulu         else if (device_id == QLOGIC_PCI_DEVICE_ID_1654)
2305727bfe38SJustin Hibbits 		if_setbaudrate(ifp, IF_Gbps(50));
230611e25f0dSDavid C Somayajulu         else if (device_id == QLOGIC_PCI_DEVICE_ID_1644)
2307727bfe38SJustin Hibbits 		if_setbaudrate(ifp, IF_Gbps(100));
230811e25f0dSDavid C Somayajulu 
2309727bfe38SJustin Hibbits         if_setcapabilities(ifp, IFCAP_LINKSTATE);
231011e25f0dSDavid C Somayajulu 
2311727bfe38SJustin Hibbits         if_setinitfn(ifp, qlnx_init);
2312727bfe38SJustin Hibbits         if_setsoftc(ifp, ha);
2313727bfe38SJustin Hibbits         if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
2314727bfe38SJustin Hibbits         if_setioctlfn(ifp, qlnx_ioctl);
2315727bfe38SJustin Hibbits         if_settransmitfn(ifp, qlnx_transmit);
2316727bfe38SJustin Hibbits         if_setqflushfn(ifp, qlnx_qflush);
231711e25f0dSDavid C Somayajulu 
2318727bfe38SJustin Hibbits         if_setsendqlen(ifp, qlnx_get_ifq_snd_maxlen(ha));
2319727bfe38SJustin Hibbits         if_setsendqready(ifp);
232011e25f0dSDavid C Somayajulu 
232111e25f0dSDavid C Somayajulu 	if_setgetcounterfn(ifp, qlnx_get_counter);
232211e25f0dSDavid C Somayajulu 
2323727bfe38SJustin Hibbits         ha->max_frame_size = if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN;
232411e25f0dSDavid C Somayajulu 
232511e25f0dSDavid C Somayajulu         memcpy(ha->primary_mac, qlnx_get_mac_addr(ha), ETH_ALEN);
2326217ec208SDavid C Somayajulu 
2327217ec208SDavid C Somayajulu 	if (!ha->primary_mac[0] && !ha->primary_mac[1] &&
2328217ec208SDavid C Somayajulu 		!ha->primary_mac[2] && !ha->primary_mac[3] &&
2329217ec208SDavid C Somayajulu 		!ha->primary_mac[4] && !ha->primary_mac[5]) {
2330217ec208SDavid C Somayajulu 		uint32_t rnd;
2331217ec208SDavid C Somayajulu 
2332217ec208SDavid C Somayajulu 		rnd = arc4random();
2333217ec208SDavid C Somayajulu 
2334217ec208SDavid C Somayajulu 		ha->primary_mac[0] = 0x00;
2335217ec208SDavid C Somayajulu 		ha->primary_mac[1] = 0x0e;
2336217ec208SDavid C Somayajulu 		ha->primary_mac[2] = 0x1e;
2337217ec208SDavid C Somayajulu 		ha->primary_mac[3] = rnd & 0xFF;
2338217ec208SDavid C Somayajulu 		ha->primary_mac[4] = (rnd >> 8) & 0xFF;
2339217ec208SDavid C Somayajulu 		ha->primary_mac[5] = (rnd >> 16) & 0xFF;
2340217ec208SDavid C Somayajulu 	}
2341217ec208SDavid C Somayajulu 
234211e25f0dSDavid C Somayajulu 	ether_ifattach(ifp, ha->primary_mac);
2343727bfe38SJustin Hibbits 	bcopy(if_getlladdr(ha->ifp), ha->primary_mac, ETHER_ADDR_LEN);
234411e25f0dSDavid C Somayajulu 
2345727bfe38SJustin Hibbits 	if_setcapabilities(ifp, IFCAP_HWCSUM);
2346727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_JUMBO_MTU, 0);
234711e25f0dSDavid C Somayajulu 
2348727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0);
2349727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWTAGGING, 0);
2350727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWFILTER, 0);
2351727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWCSUM, 0);
2352727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWTSO, 0);
2353727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_TSO4, 0);
2354727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_TSO6, 0);
2355727bfe38SJustin Hibbits 	if_setcapabilitiesbit(ifp, IFCAP_LRO, 0);
235611e25f0dSDavid C Somayajulu 
2357727bfe38SJustin Hibbits 	if_sethwtsomax(ifp,  QLNX_MAX_TSO_FRAME_SIZE -
2358727bfe38SJustin Hibbits 				(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN));
2359727bfe38SJustin Hibbits 	if_sethwtsomaxsegcount(ifp, QLNX_MAX_SEGMENTS - 1); /* hdr */
2360727bfe38SJustin Hibbits 	if_sethwtsomaxsegsize(ifp, QLNX_MAX_TX_MBUF_SIZE);
236145f13123SDavid C Somayajulu 
2362727bfe38SJustin Hibbits         if_setcapenable(ifp, if_getcapabilities(ifp));
236311e25f0dSDavid C Somayajulu 
2364727bfe38SJustin Hibbits 	if_sethwassist(ifp, CSUM_IP);
2365727bfe38SJustin Hibbits 	if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0);
2366727bfe38SJustin Hibbits 	if_sethwassistbits(ifp, CSUM_TCP_IPV6 | CSUM_UDP_IPV6, 0);
2367727bfe38SJustin Hibbits 	if_sethwassistbits(ifp, CSUM_TSO, 0);
236811e25f0dSDavid C Somayajulu 
2369727bfe38SJustin Hibbits 	if_setifheaderlen(ifp, sizeof(struct ether_vlan_header));
237011e25f0dSDavid C Somayajulu 
237111e25f0dSDavid C Somayajulu         ifmedia_init(&ha->media, IFM_IMASK, qlnx_media_change,\
237211e25f0dSDavid C Somayajulu 		qlnx_media_status);
237311e25f0dSDavid C Somayajulu 
237411e25f0dSDavid C Somayajulu         if (device_id == QLOGIC_PCI_DEVICE_ID_1634) {
237511e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | IFM_40G_LR4), 0, NULL);
237611e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | IFM_40G_SR4), 0, NULL);
237711e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | IFM_40G_CR4), 0, NULL);
23789efd0ba7SDavid C Somayajulu         } else if ((device_id == QLOGIC_PCI_DEVICE_ID_1656) ||
23799efd0ba7SDavid C Somayajulu 			(device_id == QLOGIC_PCI_DEVICE_ID_8070)) {
238011e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | QLNX_IFM_25G_SR), 0, NULL);
238111e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | QLNX_IFM_25G_CR), 0, NULL);
238211e25f0dSDavid C Somayajulu         } else if (device_id == QLOGIC_PCI_DEVICE_ID_1654) {
238311e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | IFM_50G_KR2), 0, NULL);
238411e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media, (IFM_ETHER | IFM_50G_CR2), 0, NULL);
238511e25f0dSDavid C Somayajulu         } else if (device_id == QLOGIC_PCI_DEVICE_ID_1644) {
238611e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media,
238711e25f0dSDavid C Somayajulu 			(IFM_ETHER | QLNX_IFM_100G_LR4), 0, NULL);
238811e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media,
238911e25f0dSDavid C Somayajulu 			(IFM_ETHER | QLNX_IFM_100G_SR4), 0, NULL);
239011e25f0dSDavid C Somayajulu 		ifmedia_add(&ha->media,
239111e25f0dSDavid C Somayajulu 			(IFM_ETHER | QLNX_IFM_100G_CR4), 0, NULL);
239211e25f0dSDavid C Somayajulu 	}
239311e25f0dSDavid C Somayajulu 
239411e25f0dSDavid C Somayajulu         ifmedia_add(&ha->media, (IFM_ETHER | IFM_FDX), 0, NULL);
239511e25f0dSDavid C Somayajulu         ifmedia_add(&ha->media, (IFM_ETHER | IFM_AUTO), 0, NULL);
239611e25f0dSDavid C Somayajulu 
239711e25f0dSDavid C Somayajulu         ifmedia_set(&ha->media, (IFM_ETHER | IFM_AUTO));
239811e25f0dSDavid C Somayajulu 
23997a377fbeSDavid C Somayajulu         QL_DPRINT2(ha, "exit\n");
240011e25f0dSDavid C Somayajulu 
240111e25f0dSDavid C Somayajulu         return;
240211e25f0dSDavid C Somayajulu }
240311e25f0dSDavid C Somayajulu 
240411e25f0dSDavid C Somayajulu static void
qlnx_init_locked(qlnx_host_t * ha)240511e25f0dSDavid C Somayajulu qlnx_init_locked(qlnx_host_t *ha)
240611e25f0dSDavid C Somayajulu {
2407727bfe38SJustin Hibbits 	if_t		ifp = ha->ifp;
240811e25f0dSDavid C Somayajulu 
24097a377fbeSDavid C Somayajulu 	QL_DPRINT1(ha, "Driver Initialization start \n");
24107a377fbeSDavid C Somayajulu 
241111e25f0dSDavid C Somayajulu 	qlnx_stop(ha);
241211e25f0dSDavid C Somayajulu 
241311e25f0dSDavid C Somayajulu 	if (qlnx_load(ha) == 0) {
2414727bfe38SJustin Hibbits 		if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
2415727bfe38SJustin Hibbits 		if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
2416217ec208SDavid C Somayajulu 
2417217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
2418217ec208SDavid C Somayajulu 		if (qlnx_vf_device(ha) != 0) {
2419217ec208SDavid C Somayajulu 			qlnx_rdma_dev_open(ha);
2420217ec208SDavid C Somayajulu 		}
2421217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
242211e25f0dSDavid C Somayajulu 	}
242311e25f0dSDavid C Somayajulu 
242411e25f0dSDavid C Somayajulu 	return;
242511e25f0dSDavid C Somayajulu }
242611e25f0dSDavid C Somayajulu 
242711e25f0dSDavid C Somayajulu static void
qlnx_init(void * arg)242811e25f0dSDavid C Somayajulu qlnx_init(void *arg)
242911e25f0dSDavid C Somayajulu {
243011e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
243111e25f0dSDavid C Somayajulu 
243211e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)arg;
243311e25f0dSDavid C Somayajulu 
24347a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
243511e25f0dSDavid C Somayajulu 
243611e25f0dSDavid C Somayajulu 	QLNX_LOCK(ha);
243711e25f0dSDavid C Somayajulu 	qlnx_init_locked(ha);
243811e25f0dSDavid C Somayajulu 	QLNX_UNLOCK(ha);
243911e25f0dSDavid C Somayajulu 
24407a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
244111e25f0dSDavid C Somayajulu 
244211e25f0dSDavid C Somayajulu 	return;
244311e25f0dSDavid C Somayajulu }
244411e25f0dSDavid C Somayajulu 
244511e25f0dSDavid C Somayajulu static int
qlnx_config_mcast_mac_addr(qlnx_host_t * ha,uint8_t * mac_addr,uint32_t add_mac)244611e25f0dSDavid C Somayajulu qlnx_config_mcast_mac_addr(qlnx_host_t *ha, uint8_t *mac_addr, uint32_t add_mac)
244711e25f0dSDavid C Somayajulu {
244811e25f0dSDavid C Somayajulu 	struct ecore_filter_mcast	*mcast;
244911e25f0dSDavid C Somayajulu 	struct ecore_dev		*cdev;
245011e25f0dSDavid C Somayajulu 	int				rc;
245111e25f0dSDavid C Somayajulu 
245211e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
245311e25f0dSDavid C Somayajulu 
245411e25f0dSDavid C Somayajulu 	mcast = &ha->ecore_mcast;
245511e25f0dSDavid C Somayajulu 	bzero(mcast, sizeof(struct ecore_filter_mcast));
245611e25f0dSDavid C Somayajulu 
245711e25f0dSDavid C Somayajulu 	if (add_mac)
245811e25f0dSDavid C Somayajulu 		mcast->opcode = ECORE_FILTER_ADD;
245911e25f0dSDavid C Somayajulu 	else
246011e25f0dSDavid C Somayajulu 		mcast->opcode = ECORE_FILTER_REMOVE;
246111e25f0dSDavid C Somayajulu 
246211e25f0dSDavid C Somayajulu 	mcast->num_mc_addrs = 1;
246311e25f0dSDavid C Somayajulu 	memcpy(mcast->mac, mac_addr, ETH_ALEN);
246411e25f0dSDavid C Somayajulu 
246511e25f0dSDavid C Somayajulu 	rc = ecore_filter_mcast_cmd(cdev, mcast, ECORE_SPQ_MODE_CB, NULL);
246611e25f0dSDavid C Somayajulu 
246711e25f0dSDavid C Somayajulu 	return (rc);
246811e25f0dSDavid C Somayajulu }
246911e25f0dSDavid C Somayajulu 
247011e25f0dSDavid C Somayajulu static int
qlnx_hw_add_mcast(qlnx_host_t * ha,uint8_t * mta)247111e25f0dSDavid C Somayajulu qlnx_hw_add_mcast(qlnx_host_t *ha, uint8_t *mta)
247211e25f0dSDavid C Somayajulu {
247311e25f0dSDavid C Somayajulu         int	i;
247411e25f0dSDavid C Somayajulu 
247511e25f0dSDavid C Somayajulu         for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) {
247611e25f0dSDavid C Somayajulu                 if (QL_MAC_CMP(ha->mcast[i].addr, mta) == 0)
247711e25f0dSDavid C Somayajulu                         return 0; /* its been already added */
247811e25f0dSDavid C Somayajulu         }
247911e25f0dSDavid C Somayajulu 
248011e25f0dSDavid C Somayajulu         for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) {
248111e25f0dSDavid C Somayajulu                 if ((ha->mcast[i].addr[0] == 0) &&
248211e25f0dSDavid C Somayajulu                         (ha->mcast[i].addr[1] == 0) &&
248311e25f0dSDavid C Somayajulu                         (ha->mcast[i].addr[2] == 0) &&
248411e25f0dSDavid C Somayajulu                         (ha->mcast[i].addr[3] == 0) &&
248511e25f0dSDavid C Somayajulu                         (ha->mcast[i].addr[4] == 0) &&
248611e25f0dSDavid C Somayajulu                         (ha->mcast[i].addr[5] == 0)) {
248711e25f0dSDavid C Somayajulu                         if (qlnx_config_mcast_mac_addr(ha, mta, 1))
248811e25f0dSDavid C Somayajulu                                 return (-1);
248911e25f0dSDavid C Somayajulu 
249011e25f0dSDavid C Somayajulu                         bcopy(mta, ha->mcast[i].addr, ETH_ALEN);
249111e25f0dSDavid C Somayajulu                         ha->nmcast++;
249211e25f0dSDavid C Somayajulu 
249311e25f0dSDavid C Somayajulu                         return 0;
249411e25f0dSDavid C Somayajulu                 }
249511e25f0dSDavid C Somayajulu         }
249611e25f0dSDavid C Somayajulu         return 0;
249711e25f0dSDavid C Somayajulu }
249811e25f0dSDavid C Somayajulu 
249911e25f0dSDavid C Somayajulu static int
qlnx_hw_del_mcast(qlnx_host_t * ha,uint8_t * mta)250011e25f0dSDavid C Somayajulu qlnx_hw_del_mcast(qlnx_host_t *ha, uint8_t *mta)
250111e25f0dSDavid C Somayajulu {
250211e25f0dSDavid C Somayajulu         int	i;
250311e25f0dSDavid C Somayajulu 
250411e25f0dSDavid C Somayajulu         for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) {
250511e25f0dSDavid C Somayajulu                 if (QL_MAC_CMP(ha->mcast[i].addr, mta) == 0) {
250611e25f0dSDavid C Somayajulu                         if (qlnx_config_mcast_mac_addr(ha, mta, 0))
250711e25f0dSDavid C Somayajulu                                 return (-1);
250811e25f0dSDavid C Somayajulu 
250911e25f0dSDavid C Somayajulu                         ha->mcast[i].addr[0] = 0;
251011e25f0dSDavid C Somayajulu                         ha->mcast[i].addr[1] = 0;
251111e25f0dSDavid C Somayajulu                         ha->mcast[i].addr[2] = 0;
251211e25f0dSDavid C Somayajulu                         ha->mcast[i].addr[3] = 0;
251311e25f0dSDavid C Somayajulu                         ha->mcast[i].addr[4] = 0;
251411e25f0dSDavid C Somayajulu                         ha->mcast[i].addr[5] = 0;
251511e25f0dSDavid C Somayajulu 
251611e25f0dSDavid C Somayajulu                         ha->nmcast--;
251711e25f0dSDavid C Somayajulu 
251811e25f0dSDavid C Somayajulu                         return 0;
251911e25f0dSDavid C Somayajulu                 }
252011e25f0dSDavid C Somayajulu         }
252111e25f0dSDavid C Somayajulu         return 0;
252211e25f0dSDavid C Somayajulu }
252311e25f0dSDavid C Somayajulu 
252411e25f0dSDavid C Somayajulu /*
252511e25f0dSDavid C Somayajulu  * Name: qls_hw_set_multi
252611e25f0dSDavid C Somayajulu  * Function: Sets the Multicast Addresses provided the host O.S into the
252711e25f0dSDavid C Somayajulu  *      hardware (for the given interface)
252811e25f0dSDavid C Somayajulu  */
252911e25f0dSDavid C Somayajulu static void
qlnx_hw_set_multi(qlnx_host_t * ha,uint8_t * mta,uint32_t mcnt,uint32_t add_mac)253011e25f0dSDavid C Somayajulu qlnx_hw_set_multi(qlnx_host_t *ha, uint8_t *mta, uint32_t mcnt,
253111e25f0dSDavid C Somayajulu 	uint32_t add_mac)
253211e25f0dSDavid C Somayajulu {
253311e25f0dSDavid C Somayajulu         int	i;
253411e25f0dSDavid C Somayajulu 
253511e25f0dSDavid C Somayajulu         for (i = 0; i < mcnt; i++) {
253611e25f0dSDavid C Somayajulu                 if (add_mac) {
253711e25f0dSDavid C Somayajulu                         if (qlnx_hw_add_mcast(ha, mta))
253811e25f0dSDavid C Somayajulu                                 break;
253911e25f0dSDavid C Somayajulu                 } else {
254011e25f0dSDavid C Somayajulu                         if (qlnx_hw_del_mcast(ha, mta))
254111e25f0dSDavid C Somayajulu                                 break;
254211e25f0dSDavid C Somayajulu                 }
254311e25f0dSDavid C Somayajulu 
254411e25f0dSDavid C Somayajulu                 mta += ETHER_HDR_LEN;
254511e25f0dSDavid C Somayajulu         }
254611e25f0dSDavid C Somayajulu         return;
254711e25f0dSDavid C Somayajulu }
254811e25f0dSDavid C Somayajulu 
2549fe8a3369SGleb Smirnoff static u_int
qlnx_copy_maddr(void * arg,struct sockaddr_dl * sdl,u_int mcnt)2550fe8a3369SGleb Smirnoff qlnx_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt)
2551fe8a3369SGleb Smirnoff {
2552fe8a3369SGleb Smirnoff 	uint8_t *mta = arg;
2553fe8a3369SGleb Smirnoff 
2554fe8a3369SGleb Smirnoff 	if (mcnt == QLNX_MAX_NUM_MULTICAST_ADDRS)
2555fe8a3369SGleb Smirnoff 		return (0);
2556fe8a3369SGleb Smirnoff 
2557fe8a3369SGleb Smirnoff 	bcopy(LLADDR(sdl), &mta[mcnt * ETHER_HDR_LEN], ETHER_HDR_LEN);
2558fe8a3369SGleb Smirnoff 
2559fe8a3369SGleb Smirnoff 	return (1);
2560fe8a3369SGleb Smirnoff }
2561fe8a3369SGleb Smirnoff 
256211e25f0dSDavid C Somayajulu static int
qlnx_set_multi(qlnx_host_t * ha,uint32_t add_multi)256311e25f0dSDavid C Somayajulu qlnx_set_multi(qlnx_host_t *ha, uint32_t add_multi)
256411e25f0dSDavid C Somayajulu {
2565fe8a3369SGleb Smirnoff 	uint8_t		mta[QLNX_MAX_NUM_MULTICAST_ADDRS * ETHER_HDR_LEN];
2566727bfe38SJustin Hibbits 	if_t		ifp = ha->ifp;
2567fe8a3369SGleb Smirnoff 	u_int		mcnt;
256811e25f0dSDavid C Somayajulu 
2569217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
2570217ec208SDavid C Somayajulu 		return (0);
2571217ec208SDavid C Somayajulu 
2572fe8a3369SGleb Smirnoff 	mcnt = if_foreach_llmaddr(ifp, qlnx_copy_maddr, mta);
257311e25f0dSDavid C Somayajulu 
257411e25f0dSDavid C Somayajulu 	QLNX_LOCK(ha);
257511e25f0dSDavid C Somayajulu 	qlnx_hw_set_multi(ha, mta, mcnt, add_multi);
257611e25f0dSDavid C Somayajulu 	QLNX_UNLOCK(ha);
257711e25f0dSDavid C Somayajulu 
2578fe8a3369SGleb Smirnoff 	return (0);
257911e25f0dSDavid C Somayajulu }
258011e25f0dSDavid C Somayajulu 
258111e25f0dSDavid C Somayajulu static int
qlnx_set_promisc(qlnx_host_t * ha,int enabled)2582e3ec564eSKeith Reynolds qlnx_set_promisc(qlnx_host_t *ha, int enabled)
258311e25f0dSDavid C Somayajulu {
258411e25f0dSDavid C Somayajulu 	int	rc = 0;
258511e25f0dSDavid C Somayajulu 	uint8_t	filter;
258611e25f0dSDavid C Somayajulu 
2587217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
2588217ec208SDavid C Somayajulu 		return (0);
2589217ec208SDavid C Somayajulu 
259011e25f0dSDavid C Somayajulu 	filter = ha->filter;
2591e3ec564eSKeith Reynolds 	if (enabled) {
259211e25f0dSDavid C Somayajulu 		filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
259311e25f0dSDavid C Somayajulu 		filter |= ECORE_ACCEPT_UCAST_UNMATCHED;
2594e3ec564eSKeith Reynolds 	} else {
2595e3ec564eSKeith Reynolds 		filter &= ~ECORE_ACCEPT_MCAST_UNMATCHED;
2596e3ec564eSKeith Reynolds 		filter &= ~ECORE_ACCEPT_UCAST_UNMATCHED;
2597e3ec564eSKeith Reynolds 	}
259811e25f0dSDavid C Somayajulu 
259911e25f0dSDavid C Somayajulu 	rc = qlnx_set_rx_accept_filter(ha, filter);
260011e25f0dSDavid C Somayajulu 	return (rc);
260111e25f0dSDavid C Somayajulu }
260211e25f0dSDavid C Somayajulu 
260311e25f0dSDavid C Somayajulu static int
qlnx_set_allmulti(qlnx_host_t * ha,int enabled)2604e3ec564eSKeith Reynolds qlnx_set_allmulti(qlnx_host_t *ha, int enabled)
260511e25f0dSDavid C Somayajulu {
260611e25f0dSDavid C Somayajulu 	int	rc = 0;
260711e25f0dSDavid C Somayajulu 	uint8_t	filter;
260811e25f0dSDavid C Somayajulu 
2609217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
2610217ec208SDavid C Somayajulu 		return (0);
2611217ec208SDavid C Somayajulu 
261211e25f0dSDavid C Somayajulu 	filter = ha->filter;
2613e3ec564eSKeith Reynolds 	if (enabled) {
261411e25f0dSDavid C Somayajulu 		filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
2615e3ec564eSKeith Reynolds 	} else {
2616e3ec564eSKeith Reynolds 		filter &= ~ECORE_ACCEPT_MCAST_UNMATCHED;
2617e3ec564eSKeith Reynolds 	}
261811e25f0dSDavid C Somayajulu 	rc = qlnx_set_rx_accept_filter(ha, filter);
261911e25f0dSDavid C Somayajulu 
262011e25f0dSDavid C Somayajulu 	return (rc);
262111e25f0dSDavid C Somayajulu }
262211e25f0dSDavid C Somayajulu 
262311e25f0dSDavid C Somayajulu static int
qlnx_ioctl(if_t ifp,u_long cmd,caddr_t data)2624727bfe38SJustin Hibbits qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data)
262511e25f0dSDavid C Somayajulu {
262611e25f0dSDavid C Somayajulu 	int		ret = 0, mask;
2627*1eaecc21SJustin Hibbits 	int		flags;
262811e25f0dSDavid C Somayajulu 	struct ifreq	*ifr = (struct ifreq *)data;
26295684c878SJessica Clarke #ifdef INET
263011e25f0dSDavid C Somayajulu 	struct ifaddr	*ifa = (struct ifaddr *)data;
26315684c878SJessica Clarke #endif
263211e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
263311e25f0dSDavid C Somayajulu 
2634727bfe38SJustin Hibbits 	ha = (qlnx_host_t *)if_getsoftc(ifp);
263511e25f0dSDavid C Somayajulu 
263611e25f0dSDavid C Somayajulu 	switch (cmd) {
263711e25f0dSDavid C Somayajulu 	case SIOCSIFADDR:
26387a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "SIOCSIFADDR (0x%lx)\n", cmd);
263911e25f0dSDavid C Somayajulu 
26405684c878SJessica Clarke #ifdef INET
264111e25f0dSDavid C Somayajulu 		if (ifa->ifa_addr->sa_family == AF_INET) {
2642727bfe38SJustin Hibbits 			if_setflagbits(ifp, IFF_UP, 0);
2643727bfe38SJustin Hibbits 			if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) {
264411e25f0dSDavid C Somayajulu 				QLNX_LOCK(ha);
264511e25f0dSDavid C Somayajulu 				qlnx_init_locked(ha);
264611e25f0dSDavid C Somayajulu 				QLNX_UNLOCK(ha);
264711e25f0dSDavid C Somayajulu 			}
26487a377fbeSDavid C Somayajulu 			QL_DPRINT4(ha, "SIOCSIFADDR (0x%lx) ipv4 [0x%08x]\n",
26497a377fbeSDavid C Somayajulu 				   cmd, ntohl(IA_SIN(ifa)->sin_addr.s_addr));
265011e25f0dSDavid C Somayajulu 
265111e25f0dSDavid C Somayajulu 			arp_ifinit(ifp, ifa);
26525684c878SJessica Clarke 			break;
265311e25f0dSDavid C Somayajulu 		}
26545684c878SJessica Clarke #endif
26555684c878SJessica Clarke 		ether_ioctl(ifp, cmd, data);
265611e25f0dSDavid C Somayajulu 		break;
265711e25f0dSDavid C Somayajulu 
265811e25f0dSDavid C Somayajulu 	case SIOCSIFMTU:
26597a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "SIOCSIFMTU (0x%lx)\n", cmd);
266011e25f0dSDavid C Somayajulu 
266111e25f0dSDavid C Somayajulu 		if (ifr->ifr_mtu > QLNX_MAX_MTU) {
266211e25f0dSDavid C Somayajulu 			ret = EINVAL;
266311e25f0dSDavid C Somayajulu 		} else {
266411e25f0dSDavid C Somayajulu 			QLNX_LOCK(ha);
2665727bfe38SJustin Hibbits 			if_setmtu(ifp, ifr->ifr_mtu);
266611e25f0dSDavid C Somayajulu 			ha->max_frame_size =
2667727bfe38SJustin Hibbits 				if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN;
2668727bfe38SJustin Hibbits 			if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
266911e25f0dSDavid C Somayajulu 				qlnx_init_locked(ha);
267011e25f0dSDavid C Somayajulu 			}
267111e25f0dSDavid C Somayajulu 
267211e25f0dSDavid C Somayajulu 			QLNX_UNLOCK(ha);
267311e25f0dSDavid C Somayajulu 		}
267411e25f0dSDavid C Somayajulu 
267511e25f0dSDavid C Somayajulu 		break;
267611e25f0dSDavid C Somayajulu 
267711e25f0dSDavid C Somayajulu 	case SIOCSIFFLAGS:
26787a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "SIOCSIFFLAGS (0x%lx)\n", cmd);
267911e25f0dSDavid C Somayajulu 
268011e25f0dSDavid C Somayajulu 		QLNX_LOCK(ha);
2681*1eaecc21SJustin Hibbits 		flags = if_getflags(ifp);
268211e25f0dSDavid C Somayajulu 
2683*1eaecc21SJustin Hibbits 		if (flags & IFF_UP) {
2684727bfe38SJustin Hibbits 			if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
2685*1eaecc21SJustin Hibbits 				if ((flags ^ ha->if_flags) &
268611e25f0dSDavid C Somayajulu 					IFF_PROMISC) {
2687*1eaecc21SJustin Hibbits 					ret = qlnx_set_promisc(ha, flags & IFF_PROMISC);
2688727bfe38SJustin Hibbits 				} else if ((if_getflags(ifp) ^ ha->if_flags) &
268911e25f0dSDavid C Somayajulu 					IFF_ALLMULTI) {
2690*1eaecc21SJustin Hibbits 					ret = qlnx_set_allmulti(ha, flags & IFF_ALLMULTI);
269111e25f0dSDavid C Somayajulu 				}
269211e25f0dSDavid C Somayajulu 			} else {
2693727bfe38SJustin Hibbits 				ha->max_frame_size = if_getmtu(ifp) +
269411e25f0dSDavid C Somayajulu 					ETHER_HDR_LEN + ETHER_CRC_LEN;
269511e25f0dSDavid C Somayajulu 				qlnx_init_locked(ha);
269611e25f0dSDavid C Somayajulu 			}
269711e25f0dSDavid C Somayajulu 		} else {
2698727bfe38SJustin Hibbits 			if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
269911e25f0dSDavid C Somayajulu 				qlnx_stop(ha);
270011e25f0dSDavid C Somayajulu 		}
270111e25f0dSDavid C Somayajulu 
2702e3ec564eSKeith Reynolds 		ha->if_flags = if_getflags(ifp);
270311e25f0dSDavid C Somayajulu 		QLNX_UNLOCK(ha);
270411e25f0dSDavid C Somayajulu 		break;
270511e25f0dSDavid C Somayajulu 
270611e25f0dSDavid C Somayajulu 	case SIOCADDMULTI:
27077a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "%s (0x%lx)\n", "SIOCADDMULTI", cmd);
270811e25f0dSDavid C Somayajulu 
2709727bfe38SJustin Hibbits 		if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
271011e25f0dSDavid C Somayajulu 			if (qlnx_set_multi(ha, 1))
271111e25f0dSDavid C Somayajulu 				ret = EINVAL;
271211e25f0dSDavid C Somayajulu 		}
271311e25f0dSDavid C Somayajulu 		break;
271411e25f0dSDavid C Somayajulu 
271511e25f0dSDavid C Somayajulu 	case SIOCDELMULTI:
27167a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "%s (0x%lx)\n", "SIOCDELMULTI", cmd);
271711e25f0dSDavid C Somayajulu 
2718727bfe38SJustin Hibbits 		if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
271911e25f0dSDavid C Somayajulu 			if (qlnx_set_multi(ha, 0))
272011e25f0dSDavid C Somayajulu 				ret = EINVAL;
272111e25f0dSDavid C Somayajulu 		}
272211e25f0dSDavid C Somayajulu 		break;
272311e25f0dSDavid C Somayajulu 
272411e25f0dSDavid C Somayajulu 	case SIOCSIFMEDIA:
272511e25f0dSDavid C Somayajulu 	case SIOCGIFMEDIA:
27267a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "SIOCSIFMEDIA/SIOCGIFMEDIA (0x%lx)\n", cmd);
27277a377fbeSDavid C Somayajulu 
272811e25f0dSDavid C Somayajulu 		ret = ifmedia_ioctl(ifp, ifr, &ha->media, cmd);
272911e25f0dSDavid C Somayajulu 		break;
273011e25f0dSDavid C Somayajulu 
273111e25f0dSDavid C Somayajulu 	case SIOCSIFCAP:
273211e25f0dSDavid C Somayajulu 
2733727bfe38SJustin Hibbits 		mask = ifr->ifr_reqcap ^ if_getcapenable(ifp);
273411e25f0dSDavid C Somayajulu 
27357a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "SIOCSIFCAP (0x%lx)\n", cmd);
273611e25f0dSDavid C Somayajulu 
273711e25f0dSDavid C Somayajulu 		if (mask & IFCAP_HWCSUM)
2738727bfe38SJustin Hibbits 			if_togglecapenable(ifp, IFCAP_HWCSUM);
273911e25f0dSDavid C Somayajulu 		if (mask & IFCAP_TSO4)
2740727bfe38SJustin Hibbits 			if_togglecapenable(ifp, IFCAP_TSO4);
274111e25f0dSDavid C Somayajulu 		if (mask & IFCAP_TSO6)
2742727bfe38SJustin Hibbits 			if_togglecapenable(ifp, IFCAP_TSO6);
274311e25f0dSDavid C Somayajulu 		if (mask & IFCAP_VLAN_HWTAGGING)
2744727bfe38SJustin Hibbits 			if_togglecapenable(ifp, IFCAP_VLAN_HWTAGGING);
274511e25f0dSDavid C Somayajulu 		if (mask & IFCAP_VLAN_HWTSO)
2746727bfe38SJustin Hibbits 			if_togglecapenable(ifp, IFCAP_VLAN_HWTSO);
274711e25f0dSDavid C Somayajulu 		if (mask & IFCAP_LRO)
2748727bfe38SJustin Hibbits 			if_togglecapenable(ifp, IFCAP_LRO);
274911e25f0dSDavid C Somayajulu 
2750217ec208SDavid C Somayajulu 		QLNX_LOCK(ha);
2751217ec208SDavid C Somayajulu 
2752727bfe38SJustin Hibbits 		if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
2753217ec208SDavid C Somayajulu 			qlnx_init_locked(ha);
2754217ec208SDavid C Somayajulu 
2755217ec208SDavid C Somayajulu 		QLNX_UNLOCK(ha);
275611e25f0dSDavid C Somayajulu 
275711e25f0dSDavid C Somayajulu 		VLAN_CAPABILITIES(ifp);
275811e25f0dSDavid C Somayajulu 		break;
275911e25f0dSDavid C Somayajulu 
276011e25f0dSDavid C Somayajulu 	case SIOCGI2C:
276111e25f0dSDavid C Somayajulu 	{
276211e25f0dSDavid C Somayajulu 		struct ifi2creq i2c;
276311e25f0dSDavid C Somayajulu 		struct ecore_hwfn *p_hwfn = &ha->cdev.hwfns[0];
276411e25f0dSDavid C Somayajulu 		struct ecore_ptt *p_ptt;
276511e25f0dSDavid C Somayajulu 
2766541d96aaSBrooks Davis 		ret = copyin(ifr_data_get_ptr(ifr), &i2c, sizeof(i2c));
276711e25f0dSDavid C Somayajulu 
276811e25f0dSDavid C Somayajulu 		if (ret)
276911e25f0dSDavid C Somayajulu 			break;
277011e25f0dSDavid C Somayajulu 
277111e25f0dSDavid C Somayajulu 		if ((i2c.len > sizeof (i2c.data)) ||
277211e25f0dSDavid C Somayajulu 			(i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2)) {
277311e25f0dSDavid C Somayajulu 			ret = EINVAL;
277411e25f0dSDavid C Somayajulu 			break;
277511e25f0dSDavid C Somayajulu 		}
277611e25f0dSDavid C Somayajulu 
277711e25f0dSDavid C Somayajulu 		p_ptt = ecore_ptt_acquire(p_hwfn);
277811e25f0dSDavid C Somayajulu 
277911e25f0dSDavid C Somayajulu 		if (!p_ptt) {
27807a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "ecore_ptt_acquire failed\n");
278111e25f0dSDavid C Somayajulu 			ret = -1;
278211e25f0dSDavid C Somayajulu 			break;
278311e25f0dSDavid C Somayajulu 		}
278411e25f0dSDavid C Somayajulu 
278511e25f0dSDavid C Somayajulu 		ret = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt,
278611e25f0dSDavid C Somayajulu 			(ha->pci_func & 0x1), i2c.dev_addr, i2c.offset,
278711e25f0dSDavid C Somayajulu 			i2c.len, &i2c.data[0]);
278811e25f0dSDavid C Somayajulu 
278911e25f0dSDavid C Somayajulu 		ecore_ptt_release(p_hwfn, p_ptt);
279011e25f0dSDavid C Somayajulu 
279111e25f0dSDavid C Somayajulu 		if (ret) {
279211e25f0dSDavid C Somayajulu 			ret = -1;
279311e25f0dSDavid C Somayajulu 			break;
279411e25f0dSDavid C Somayajulu 		}
279511e25f0dSDavid C Somayajulu 
2796541d96aaSBrooks Davis 		ret = copyout(&i2c, ifr_data_get_ptr(ifr), sizeof(i2c));
279711e25f0dSDavid C Somayajulu 
27987a377fbeSDavid C Somayajulu 		QL_DPRINT8(ha, "SIOCGI2C copyout ret = %d \
27997a377fbeSDavid C Somayajulu 			 len = %d addr = 0x%02x offset = 0x%04x \
28007a377fbeSDavid C Somayajulu 			 data[0..7]=0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \
28017a377fbeSDavid C Somayajulu 			 0x%02x 0x%02x 0x%02x\n",
280211e25f0dSDavid C Somayajulu 			ret, i2c.len, i2c.dev_addr, i2c.offset,
280311e25f0dSDavid C Somayajulu 			i2c.data[0], i2c.data[1], i2c.data[2], i2c.data[3],
28047a377fbeSDavid C Somayajulu 			i2c.data[4], i2c.data[5], i2c.data[6], i2c.data[7]);
280511e25f0dSDavid C Somayajulu 		break;
280611e25f0dSDavid C Somayajulu 	}
280711e25f0dSDavid C Somayajulu 
280811e25f0dSDavid C Somayajulu 	default:
28097a377fbeSDavid C Somayajulu 		QL_DPRINT4(ha, "default (0x%lx)\n", cmd);
281011e25f0dSDavid C Somayajulu 		ret = ether_ioctl(ifp, cmd, data);
281111e25f0dSDavid C Somayajulu 		break;
281211e25f0dSDavid C Somayajulu 	}
281311e25f0dSDavid C Somayajulu 
281411e25f0dSDavid C Somayajulu 	return (ret);
281511e25f0dSDavid C Somayajulu }
281611e25f0dSDavid C Somayajulu 
281711e25f0dSDavid C Somayajulu static int
qlnx_media_change(if_t ifp)2818727bfe38SJustin Hibbits qlnx_media_change(if_t ifp)
281911e25f0dSDavid C Somayajulu {
282011e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
282111e25f0dSDavid C Somayajulu 	struct ifmedia	*ifm;
282211e25f0dSDavid C Somayajulu 	int		ret = 0;
282311e25f0dSDavid C Somayajulu 
2824727bfe38SJustin Hibbits 	ha = (qlnx_host_t *)if_getsoftc(ifp);
282511e25f0dSDavid C Somayajulu 
28267a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
282711e25f0dSDavid C Somayajulu 
282811e25f0dSDavid C Somayajulu 	ifm = &ha->media;
282911e25f0dSDavid C Somayajulu 
283011e25f0dSDavid C Somayajulu 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
283111e25f0dSDavid C Somayajulu 		ret = EINVAL;
283211e25f0dSDavid C Somayajulu 
28337a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
283411e25f0dSDavid C Somayajulu 
283511e25f0dSDavid C Somayajulu 	return (ret);
283611e25f0dSDavid C Somayajulu }
283711e25f0dSDavid C Somayajulu 
283811e25f0dSDavid C Somayajulu static void
qlnx_media_status(if_t ifp,struct ifmediareq * ifmr)2839727bfe38SJustin Hibbits qlnx_media_status(if_t ifp, struct ifmediareq *ifmr)
284011e25f0dSDavid C Somayajulu {
284111e25f0dSDavid C Somayajulu 	qlnx_host_t		*ha;
284211e25f0dSDavid C Somayajulu 
2843727bfe38SJustin Hibbits 	ha = (qlnx_host_t *)if_getsoftc(ifp);
284411e25f0dSDavid C Somayajulu 
28457a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
284611e25f0dSDavid C Somayajulu 
284711e25f0dSDavid C Somayajulu 	ifmr->ifm_status = IFM_AVALID;
284811e25f0dSDavid C Somayajulu 	ifmr->ifm_active = IFM_ETHER;
284911e25f0dSDavid C Somayajulu 
285011e25f0dSDavid C Somayajulu 	if (ha->link_up) {
285111e25f0dSDavid C Somayajulu 		ifmr->ifm_status |= IFM_ACTIVE;
285211e25f0dSDavid C Somayajulu 		ifmr->ifm_active |=
285311e25f0dSDavid C Somayajulu 			(IFM_FDX | qlnx_get_optics(ha, &ha->if_link));
285411e25f0dSDavid C Somayajulu 
285511e25f0dSDavid C Somayajulu 		if (ha->if_link.link_partner_caps &
285611e25f0dSDavid C Somayajulu 			(QLNX_LINK_CAP_Pause | QLNX_LINK_CAP_Asym_Pause))
285711e25f0dSDavid C Somayajulu 			ifmr->ifm_active |=
285811e25f0dSDavid C Somayajulu 				(IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
285911e25f0dSDavid C Somayajulu 	}
286011e25f0dSDavid C Somayajulu 
28617a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit (%s)\n", (ha->link_up ? "link_up" : "link_down"));
286211e25f0dSDavid C Somayajulu 
286311e25f0dSDavid C Somayajulu 	return;
286411e25f0dSDavid C Somayajulu }
286511e25f0dSDavid C Somayajulu 
286611e25f0dSDavid C Somayajulu static void
qlnx_free_tx_pkt(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_tx_queue * txq)286711e25f0dSDavid C Somayajulu qlnx_free_tx_pkt(qlnx_host_t *ha, struct qlnx_fastpath *fp,
286811e25f0dSDavid C Somayajulu 	struct qlnx_tx_queue *txq)
286911e25f0dSDavid C Somayajulu {
287011e25f0dSDavid C Somayajulu 	u16			idx;
287111e25f0dSDavid C Somayajulu 	struct mbuf		*mp;
287211e25f0dSDavid C Somayajulu 	bus_dmamap_t		map;
287311e25f0dSDavid C Somayajulu 	int			i;
2874885db930SJohn Baldwin //	struct eth_tx_bd	*tx_data_bd;
287511e25f0dSDavid C Somayajulu 	struct eth_tx_1st_bd	*first_bd;
287611e25f0dSDavid C Somayajulu 	int			nbds = 0;
287711e25f0dSDavid C Somayajulu 
287811e25f0dSDavid C Somayajulu 	idx = txq->sw_tx_cons;
287911e25f0dSDavid C Somayajulu 	mp = txq->sw_tx_ring[idx].mp;
288011e25f0dSDavid C Somayajulu 	map = txq->sw_tx_ring[idx].map;
288111e25f0dSDavid C Somayajulu 
288211e25f0dSDavid C Somayajulu 	if ((mp == NULL) || QL_ERR_INJECT(ha, QL_ERR_INJCT_TX_INT_MBUF_NULL)){
288311e25f0dSDavid C Somayajulu 		QL_RESET_ERR_INJECT(ha, QL_ERR_INJCT_TX_INT_MBUF_NULL);
288411e25f0dSDavid C Somayajulu 
28857a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "(mp == NULL) "
288611e25f0dSDavid C Somayajulu 			" tx_idx = 0x%x"
288711e25f0dSDavid C Somayajulu 			" ecore_prod_idx = 0x%x"
288811e25f0dSDavid C Somayajulu 			" ecore_cons_idx = 0x%x"
288911e25f0dSDavid C Somayajulu 			" hw_bd_cons = 0x%x"
289011e25f0dSDavid C Somayajulu 			" txq_db_last = 0x%x"
289111e25f0dSDavid C Somayajulu 			" elem_left = 0x%x\n",
289211e25f0dSDavid C Somayajulu 			fp->rss_id,
289311e25f0dSDavid C Somayajulu 			ecore_chain_get_prod_idx(&txq->tx_pbl),
289411e25f0dSDavid C Somayajulu 			ecore_chain_get_cons_idx(&txq->tx_pbl),
289511e25f0dSDavid C Somayajulu 			le16toh(*txq->hw_cons_ptr),
289611e25f0dSDavid C Somayajulu 			txq->tx_db.raw,
28977a377fbeSDavid C Somayajulu 			ecore_chain_get_elem_left(&txq->tx_pbl));
289811e25f0dSDavid C Somayajulu 
289911e25f0dSDavid C Somayajulu 		fp->err_tx_free_pkt_null++;
290011e25f0dSDavid C Somayajulu 
290111e25f0dSDavid C Somayajulu 		//DEBUG
290211e25f0dSDavid C Somayajulu 		qlnx_trigger_dump(ha);
290311e25f0dSDavid C Somayajulu 
290411e25f0dSDavid C Somayajulu 		return;
290511e25f0dSDavid C Somayajulu 	} else {
290611e25f0dSDavid C Somayajulu 		QLNX_INC_OPACKETS((ha->ifp));
290711e25f0dSDavid C Somayajulu 		QLNX_INC_OBYTES((ha->ifp), (mp->m_pkthdr.len));
290811e25f0dSDavid C Somayajulu 
290911e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->tx_tag, map, BUS_DMASYNC_POSTWRITE);
291011e25f0dSDavid C Somayajulu 		bus_dmamap_unload(ha->tx_tag, map);
291111e25f0dSDavid C Somayajulu 
291211e25f0dSDavid C Somayajulu 		fp->tx_pkts_freed++;
291311e25f0dSDavid C Somayajulu 		fp->tx_pkts_completed++;
291411e25f0dSDavid C Somayajulu 
291511e25f0dSDavid C Somayajulu 		m_freem(mp);
291611e25f0dSDavid C Somayajulu 	}
291711e25f0dSDavid C Somayajulu 
291811e25f0dSDavid C Somayajulu 	first_bd = (struct eth_tx_1st_bd *)ecore_chain_consume(&txq->tx_pbl);
291911e25f0dSDavid C Somayajulu 	nbds = first_bd->data.nbds;
292011e25f0dSDavid C Somayajulu 
292111e25f0dSDavid C Somayajulu //	BD_SET_UNMAP_ADDR_LEN(first_bd, 0, 0);
292211e25f0dSDavid C Somayajulu 
292311e25f0dSDavid C Somayajulu 	for (i = 1; i < nbds; i++) {
2924885db930SJohn Baldwin 		/* tx_data_bd = */ ecore_chain_consume(&txq->tx_pbl);
292511e25f0dSDavid C Somayajulu //		BD_SET_UNMAP_ADDR_LEN(tx_data_bd, 0, 0);
292611e25f0dSDavid C Somayajulu 	}
292711e25f0dSDavid C Somayajulu 	txq->sw_tx_ring[idx].flags = 0;
292811e25f0dSDavid C Somayajulu 	txq->sw_tx_ring[idx].mp = NULL;
292911e25f0dSDavid C Somayajulu 	txq->sw_tx_ring[idx].map = (bus_dmamap_t)0;
293011e25f0dSDavid C Somayajulu 
293111e25f0dSDavid C Somayajulu 	return;
293211e25f0dSDavid C Somayajulu }
293311e25f0dSDavid C Somayajulu 
293411e25f0dSDavid C Somayajulu static void
qlnx_tx_int(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_tx_queue * txq)293511e25f0dSDavid C Somayajulu qlnx_tx_int(qlnx_host_t *ha, struct qlnx_fastpath *fp,
293611e25f0dSDavid C Somayajulu 	struct qlnx_tx_queue *txq)
293711e25f0dSDavid C Somayajulu {
293811e25f0dSDavid C Somayajulu 	u16 hw_bd_cons;
293911e25f0dSDavid C Somayajulu 	u16 ecore_cons_idx;
294011e25f0dSDavid C Somayajulu 	uint16_t diff;
294145f13123SDavid C Somayajulu 	uint16_t idx, idx2;
294211e25f0dSDavid C Somayajulu 
294311e25f0dSDavid C Somayajulu 	hw_bd_cons = le16toh(*txq->hw_cons_ptr);
294411e25f0dSDavid C Somayajulu 
294511e25f0dSDavid C Somayajulu 	while (hw_bd_cons !=
294611e25f0dSDavid C Somayajulu 		(ecore_cons_idx = ecore_chain_get_cons_idx(&txq->tx_pbl))) {
294711e25f0dSDavid C Somayajulu 		diff = hw_bd_cons - ecore_cons_idx;
294811e25f0dSDavid C Somayajulu 		if ((diff > TX_RING_SIZE) ||
294911e25f0dSDavid C Somayajulu 			QL_ERR_INJECT(ha, QL_ERR_INJCT_TX_INT_DIFF)){
295011e25f0dSDavid C Somayajulu 			QL_RESET_ERR_INJECT(ha, QL_ERR_INJCT_TX_INT_DIFF);
295111e25f0dSDavid C Somayajulu 
29527a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "(diff = 0x%x) "
295311e25f0dSDavid C Somayajulu 				" tx_idx = 0x%x"
295411e25f0dSDavid C Somayajulu 				" ecore_prod_idx = 0x%x"
295511e25f0dSDavid C Somayajulu 				" ecore_cons_idx = 0x%x"
295611e25f0dSDavid C Somayajulu 				" hw_bd_cons = 0x%x"
295711e25f0dSDavid C Somayajulu 				" txq_db_last = 0x%x"
295811e25f0dSDavid C Somayajulu 				" elem_left = 0x%x\n",
29597a377fbeSDavid C Somayajulu 				diff,
296011e25f0dSDavid C Somayajulu 				fp->rss_id,
296111e25f0dSDavid C Somayajulu 				ecore_chain_get_prod_idx(&txq->tx_pbl),
296211e25f0dSDavid C Somayajulu 				ecore_chain_get_cons_idx(&txq->tx_pbl),
296311e25f0dSDavid C Somayajulu 				le16toh(*txq->hw_cons_ptr),
296411e25f0dSDavid C Somayajulu 				txq->tx_db.raw,
29657a377fbeSDavid C Somayajulu 				ecore_chain_get_elem_left(&txq->tx_pbl));
296611e25f0dSDavid C Somayajulu 
296711e25f0dSDavid C Somayajulu 			fp->err_tx_cons_idx_conflict++;
296811e25f0dSDavid C Somayajulu 
296911e25f0dSDavid C Somayajulu 			//DEBUG
297011e25f0dSDavid C Somayajulu 			qlnx_trigger_dump(ha);
297111e25f0dSDavid C Somayajulu 		}
297211e25f0dSDavid C Somayajulu 
297345f13123SDavid C Somayajulu 		idx = (txq->sw_tx_cons + 1) & (TX_RING_SIZE - 1);
297445f13123SDavid C Somayajulu 		idx2 = (txq->sw_tx_cons + 2) & (TX_RING_SIZE - 1);
297545f13123SDavid C Somayajulu 		prefetch(txq->sw_tx_ring[idx].mp);
297645f13123SDavid C Somayajulu 		prefetch(txq->sw_tx_ring[idx2].mp);
297745f13123SDavid C Somayajulu 
297811e25f0dSDavid C Somayajulu 		qlnx_free_tx_pkt(ha, fp, txq);
297911e25f0dSDavid C Somayajulu 
298011e25f0dSDavid C Somayajulu 		txq->sw_tx_cons = (txq->sw_tx_cons + 1) & (TX_RING_SIZE - 1);
298111e25f0dSDavid C Somayajulu 	}
298211e25f0dSDavid C Somayajulu 	return;
298311e25f0dSDavid C Somayajulu }
298411e25f0dSDavid C Somayajulu 
298511e25f0dSDavid C Somayajulu static int
qlnx_transmit_locked(if_t ifp,struct qlnx_fastpath * fp,struct mbuf * mp)2986727bfe38SJustin Hibbits qlnx_transmit_locked(if_t ifp, struct qlnx_fastpath *fp, struct mbuf *mp)
298745f13123SDavid C Somayajulu {
298845f13123SDavid C Somayajulu         int                     ret = 0;
298945f13123SDavid C Somayajulu         struct qlnx_tx_queue    *txq;
299045f13123SDavid C Somayajulu         qlnx_host_t *           ha;
299145f13123SDavid C Somayajulu         uint16_t elem_left;
299245f13123SDavid C Somayajulu 
299345f13123SDavid C Somayajulu         txq = fp->txq[0];
299445f13123SDavid C Somayajulu         ha = (qlnx_host_t *)fp->edev;
299545f13123SDavid C Somayajulu 
2996727bfe38SJustin Hibbits         if ((!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) || (!ha->link_up)) {
299745f13123SDavid C Somayajulu                 if(mp != NULL)
299845f13123SDavid C Somayajulu                         ret = drbr_enqueue(ifp, fp->tx_br, mp);
299945f13123SDavid C Somayajulu                 return (ret);
300045f13123SDavid C Somayajulu         }
300145f13123SDavid C Somayajulu 
300245f13123SDavid C Somayajulu         if(mp != NULL)
300345f13123SDavid C Somayajulu                 ret  = drbr_enqueue(ifp, fp->tx_br, mp);
300445f13123SDavid C Somayajulu 
300545f13123SDavid C Somayajulu         mp = drbr_peek(ifp, fp->tx_br);
300645f13123SDavid C Somayajulu 
300745f13123SDavid C Somayajulu         while (mp != NULL) {
300845f13123SDavid C Somayajulu                 if (qlnx_send(ha, fp, &mp)) {
300945f13123SDavid C Somayajulu                         if (mp != NULL) {
301045f13123SDavid C Somayajulu                                 drbr_putback(ifp, fp->tx_br, mp);
301145f13123SDavid C Somayajulu                         } else {
301245f13123SDavid C Somayajulu                                 fp->tx_pkts_processed++;
301345f13123SDavid C Somayajulu                                 drbr_advance(ifp, fp->tx_br);
301445f13123SDavid C Somayajulu                         }
301545f13123SDavid C Somayajulu                         goto qlnx_transmit_locked_exit;
301645f13123SDavid C Somayajulu 
301745f13123SDavid C Somayajulu                 } else {
301845f13123SDavid C Somayajulu                         drbr_advance(ifp, fp->tx_br);
301945f13123SDavid C Somayajulu                         fp->tx_pkts_transmitted++;
302045f13123SDavid C Somayajulu                         fp->tx_pkts_processed++;
302145f13123SDavid C Somayajulu                 }
302245f13123SDavid C Somayajulu 
302345f13123SDavid C Somayajulu                 mp = drbr_peek(ifp, fp->tx_br);
302445f13123SDavid C Somayajulu         }
302545f13123SDavid C Somayajulu 
302645f13123SDavid C Somayajulu qlnx_transmit_locked_exit:
302745f13123SDavid C Somayajulu         if((qlnx_num_tx_compl(ha,fp, fp->txq[0]) > QLNX_TX_COMPL_THRESH) ||
302845f13123SDavid C Somayajulu                 ((int)(elem_left = ecore_chain_get_elem_left(&txq->tx_pbl))
302945f13123SDavid C Somayajulu                                         < QLNX_TX_ELEM_MAX_THRESH))
303045f13123SDavid C Somayajulu                 (void)qlnx_tx_int(ha, fp, fp->txq[0]);
303145f13123SDavid C Somayajulu 
303245f13123SDavid C Somayajulu         QL_DPRINT2(ha, "%s: exit ret = %d\n", __func__, ret);
303345f13123SDavid C Somayajulu         return ret;
303445f13123SDavid C Somayajulu }
303545f13123SDavid C Somayajulu 
303645f13123SDavid C Somayajulu static int
qlnx_transmit(if_t ifp,struct mbuf * mp)3037727bfe38SJustin Hibbits qlnx_transmit(if_t ifp, struct mbuf  *mp)
303811e25f0dSDavid C Somayajulu {
3039727bfe38SJustin Hibbits         qlnx_host_t		*ha = (qlnx_host_t *)if_getsoftc(ifp);
304011e25f0dSDavid C Somayajulu         struct qlnx_fastpath	*fp;
304111e25f0dSDavid C Somayajulu         int			rss_id = 0, ret = 0;
304211e25f0dSDavid C Somayajulu 
304345f13123SDavid C Somayajulu #ifdef QLNX_TRACEPERF_DATA
304445f13123SDavid C Somayajulu         uint64_t tx_pkts = 0, tx_compl = 0;
304545f13123SDavid C Somayajulu #endif
304645f13123SDavid C Somayajulu 
30477a377fbeSDavid C Somayajulu         QL_DPRINT2(ha, "enter\n");
304811e25f0dSDavid C Somayajulu 
304911e25f0dSDavid C Somayajulu         if (M_HASHTYPE_GET(mp) != M_HASHTYPE_NONE)
305011e25f0dSDavid C Somayajulu                 rss_id = (mp->m_pkthdr.flowid % ECORE_RSS_IND_TABLE_SIZE) %
305111e25f0dSDavid C Somayajulu 					ha->num_rss;
305211e25f0dSDavid C Somayajulu 
305311e25f0dSDavid C Somayajulu         fp = &ha->fp_array[rss_id];
305411e25f0dSDavid C Somayajulu 
305511e25f0dSDavid C Somayajulu         if (fp->tx_br == NULL) {
305611e25f0dSDavid C Somayajulu                 ret = EINVAL;
305711e25f0dSDavid C Somayajulu                 goto qlnx_transmit_exit;
305811e25f0dSDavid C Somayajulu         }
305911e25f0dSDavid C Somayajulu 
306045f13123SDavid C Somayajulu         if (mtx_trylock(&fp->tx_mtx)) {
306145f13123SDavid C Somayajulu #ifdef QLNX_TRACEPERF_DATA
306245f13123SDavid C Somayajulu                         tx_pkts = fp->tx_pkts_transmitted;
306345f13123SDavid C Somayajulu                         tx_compl = fp->tx_pkts_completed;
306445f13123SDavid C Somayajulu #endif
306545f13123SDavid C Somayajulu 
306645f13123SDavid C Somayajulu                         ret = qlnx_transmit_locked(ifp, fp, mp);
306745f13123SDavid C Somayajulu 
306845f13123SDavid C Somayajulu #ifdef QLNX_TRACEPERF_DATA
306945f13123SDavid C Somayajulu                         fp->tx_pkts_trans_ctx += (fp->tx_pkts_transmitted - tx_pkts);
307045f13123SDavid C Somayajulu                         fp->tx_pkts_compl_ctx += (fp->tx_pkts_completed - tx_compl);
307145f13123SDavid C Somayajulu #endif
307245f13123SDavid C Somayajulu                         mtx_unlock(&fp->tx_mtx);
307345f13123SDavid C Somayajulu         } else {
307445f13123SDavid C Somayajulu                 if (mp != NULL && (fp->fp_taskqueue != NULL)) {
307511e25f0dSDavid C Somayajulu                         ret = drbr_enqueue(ifp, fp->tx_br, mp);
307611e25f0dSDavid C Somayajulu                         taskqueue_enqueue(fp->fp_taskqueue, &fp->fp_task);
307745f13123SDavid C Somayajulu                 }
307845f13123SDavid C Somayajulu         }
307911e25f0dSDavid C Somayajulu 
308011e25f0dSDavid C Somayajulu qlnx_transmit_exit:
308111e25f0dSDavid C Somayajulu 
30827a377fbeSDavid C Somayajulu         QL_DPRINT2(ha, "exit ret = %d\n", ret);
308311e25f0dSDavid C Somayajulu         return ret;
308411e25f0dSDavid C Somayajulu }
308511e25f0dSDavid C Somayajulu 
308611e25f0dSDavid C Somayajulu static void
qlnx_qflush(if_t ifp)3087727bfe38SJustin Hibbits qlnx_qflush(if_t ifp)
308811e25f0dSDavid C Somayajulu {
308911e25f0dSDavid C Somayajulu 	int			rss_id;
309011e25f0dSDavid C Somayajulu 	struct qlnx_fastpath	*fp;
309111e25f0dSDavid C Somayajulu 	struct mbuf		*mp;
309211e25f0dSDavid C Somayajulu 	qlnx_host_t		*ha;
309311e25f0dSDavid C Somayajulu 
3094727bfe38SJustin Hibbits 	ha = (qlnx_host_t *)if_getsoftc(ifp);
309511e25f0dSDavid C Somayajulu 
30967a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
309711e25f0dSDavid C Somayajulu 
309811e25f0dSDavid C Somayajulu 	for (rss_id = 0; rss_id < ha->num_rss; rss_id++) {
309911e25f0dSDavid C Somayajulu 		fp = &ha->fp_array[rss_id];
310011e25f0dSDavid C Somayajulu 
310111e25f0dSDavid C Somayajulu 		if (fp == NULL)
310211e25f0dSDavid C Somayajulu 			continue;
310311e25f0dSDavid C Somayajulu 
310411e25f0dSDavid C Somayajulu 		if (fp->tx_br) {
310511e25f0dSDavid C Somayajulu 			mtx_lock(&fp->tx_mtx);
310611e25f0dSDavid C Somayajulu 
310711e25f0dSDavid C Somayajulu 			while ((mp = drbr_dequeue(ifp, fp->tx_br)) != NULL) {
310811e25f0dSDavid C Somayajulu 				fp->tx_pkts_freed++;
310911e25f0dSDavid C Somayajulu 				m_freem(mp);
311011e25f0dSDavid C Somayajulu 			}
311111e25f0dSDavid C Somayajulu 			mtx_unlock(&fp->tx_mtx);
311211e25f0dSDavid C Somayajulu 		}
311311e25f0dSDavid C Somayajulu 	}
31147a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
311511e25f0dSDavid C Somayajulu 
311611e25f0dSDavid C Somayajulu 	return;
311711e25f0dSDavid C Somayajulu }
311811e25f0dSDavid C Somayajulu 
311911e25f0dSDavid C Somayajulu static void
qlnx_txq_doorbell_wr32(qlnx_host_t * ha,void * reg_addr,uint32_t value)312011e25f0dSDavid C Somayajulu qlnx_txq_doorbell_wr32(qlnx_host_t *ha, void *reg_addr, uint32_t value)
312111e25f0dSDavid C Somayajulu {
312211e25f0dSDavid C Somayajulu 	uint32_t		offset;
312311e25f0dSDavid C Somayajulu 
3124217ec208SDavid C Somayajulu 	offset = (uint32_t)((uint8_t *)reg_addr - (uint8_t *)ha->pci_dbells);
312511e25f0dSDavid C Somayajulu 
312611e25f0dSDavid C Somayajulu 	bus_write_4(ha->pci_dbells, offset, value);
312711e25f0dSDavid C Somayajulu 	bus_barrier(ha->pci_reg,  0, 0, BUS_SPACE_BARRIER_READ);
312811e25f0dSDavid C Somayajulu 	bus_barrier(ha->pci_dbells,  0, 0, BUS_SPACE_BARRIER_READ);
312911e25f0dSDavid C Somayajulu 
313011e25f0dSDavid C Somayajulu 	return;
313111e25f0dSDavid C Somayajulu }
313211e25f0dSDavid C Somayajulu 
313311e25f0dSDavid C Somayajulu static uint32_t
qlnx_tcp_offset(qlnx_host_t * ha,struct mbuf * mp)313411e25f0dSDavid C Somayajulu qlnx_tcp_offset(qlnx_host_t *ha, struct mbuf *mp)
313511e25f0dSDavid C Somayajulu {
313611e25f0dSDavid C Somayajulu         struct ether_vlan_header	*eh = NULL;
313711e25f0dSDavid C Somayajulu         struct ip			*ip = NULL;
313811e25f0dSDavid C Somayajulu         struct ip6_hdr			*ip6 = NULL;
313911e25f0dSDavid C Somayajulu         struct tcphdr			*th = NULL;
314011e25f0dSDavid C Somayajulu         uint32_t			ehdrlen = 0, ip_hlen = 0, offset = 0;
314111e25f0dSDavid C Somayajulu         uint16_t			etype = 0;
314211e25f0dSDavid C Somayajulu         uint8_t				buf[sizeof(struct ip6_hdr)];
314311e25f0dSDavid C Somayajulu 
314411e25f0dSDavid C Somayajulu         eh = mtod(mp, struct ether_vlan_header *);
314511e25f0dSDavid C Somayajulu 
314611e25f0dSDavid C Somayajulu         if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
314711e25f0dSDavid C Somayajulu                 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
314811e25f0dSDavid C Somayajulu                 etype = ntohs(eh->evl_proto);
314911e25f0dSDavid C Somayajulu         } else {
315011e25f0dSDavid C Somayajulu                 ehdrlen = ETHER_HDR_LEN;
315111e25f0dSDavid C Somayajulu                 etype = ntohs(eh->evl_encap_proto);
315211e25f0dSDavid C Somayajulu         }
315311e25f0dSDavid C Somayajulu 
315411e25f0dSDavid C Somayajulu         switch (etype) {
315511e25f0dSDavid C Somayajulu                 case ETHERTYPE_IP:
315611e25f0dSDavid C Somayajulu                         ip = (struct ip *)(mp->m_data + ehdrlen);
315711e25f0dSDavid C Somayajulu 
315811e25f0dSDavid C Somayajulu                         ip_hlen = sizeof (struct ip);
315911e25f0dSDavid C Somayajulu 
316011e25f0dSDavid C Somayajulu                         if (mp->m_len < (ehdrlen + ip_hlen)) {
316111e25f0dSDavid C Somayajulu                                 m_copydata(mp, ehdrlen, sizeof(struct ip), buf);
316211e25f0dSDavid C Somayajulu                                 ip = (struct ip *)buf;
316311e25f0dSDavid C Somayajulu                         }
316411e25f0dSDavid C Somayajulu 
316511e25f0dSDavid C Somayajulu                         th = (struct tcphdr *)(ip + 1);
316611e25f0dSDavid C Somayajulu 			offset = ip_hlen + ehdrlen + (th->th_off << 2);
316711e25f0dSDavid C Somayajulu                 break;
316811e25f0dSDavid C Somayajulu 
316911e25f0dSDavid C Somayajulu                 case ETHERTYPE_IPV6:
317011e25f0dSDavid C Somayajulu                         ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
317111e25f0dSDavid C Somayajulu 
317211e25f0dSDavid C Somayajulu                         ip_hlen = sizeof(struct ip6_hdr);
317311e25f0dSDavid C Somayajulu 
317411e25f0dSDavid C Somayajulu                         if (mp->m_len < (ehdrlen + ip_hlen)) {
317511e25f0dSDavid C Somayajulu                                 m_copydata(mp, ehdrlen, sizeof (struct ip6_hdr),
317611e25f0dSDavid C Somayajulu                                         buf);
317711e25f0dSDavid C Somayajulu                                 ip6 = (struct ip6_hdr *)buf;
317811e25f0dSDavid C Somayajulu                         }
317911e25f0dSDavid C Somayajulu                         th = (struct tcphdr *)(ip6 + 1);
318011e25f0dSDavid C Somayajulu 			offset = ip_hlen + ehdrlen + (th->th_off << 2);
318111e25f0dSDavid C Somayajulu                 break;
318211e25f0dSDavid C Somayajulu 
318311e25f0dSDavid C Somayajulu                 default:
318411e25f0dSDavid C Somayajulu                 break;
318511e25f0dSDavid C Somayajulu         }
318611e25f0dSDavid C Somayajulu 
318711e25f0dSDavid C Somayajulu         return (offset);
318811e25f0dSDavid C Somayajulu }
318911e25f0dSDavid C Somayajulu 
319011e25f0dSDavid C Somayajulu static __inline int
qlnx_tso_check(struct qlnx_fastpath * fp,bus_dma_segment_t * segs,int nsegs,uint32_t offset)319111e25f0dSDavid C Somayajulu qlnx_tso_check(struct qlnx_fastpath *fp, bus_dma_segment_t *segs, int nsegs,
319211e25f0dSDavid C Somayajulu 	uint32_t offset)
319311e25f0dSDavid C Somayajulu {
319411e25f0dSDavid C Somayajulu 	int			i;
319511e25f0dSDavid C Somayajulu 	uint32_t		sum, nbds_in_hdr = 1;
3196b1c4d096SDavid C Somayajulu         uint32_t		window;
3197b1c4d096SDavid C Somayajulu         bus_dma_segment_t	*s_seg;
319811e25f0dSDavid C Somayajulu 
319978fc83f0SGordon Bergling         /* If the header spans multiple segments, skip those segments */
3200b1c4d096SDavid C Somayajulu 
3201b1c4d096SDavid C Somayajulu         if (nsegs < ETH_TX_LSO_WINDOW_BDS_NUM)
3202b1c4d096SDavid C Somayajulu                 return (0);
320311e25f0dSDavid C Somayajulu 
320411e25f0dSDavid C Somayajulu         i = 0;
3205b1c4d096SDavid C Somayajulu 
3206b1c4d096SDavid C Somayajulu         while ((i < nsegs) && (offset >= segs->ds_len)) {
3207b1c4d096SDavid C Somayajulu                 offset = offset - segs->ds_len;
3208b1c4d096SDavid C Somayajulu                 segs++;
320911e25f0dSDavid C Somayajulu                 i++;
3210b1c4d096SDavid C Somayajulu                 nbds_in_hdr++;
321111e25f0dSDavid C Somayajulu         }
321211e25f0dSDavid C Somayajulu 
3213b1c4d096SDavid C Somayajulu         window = ETH_TX_LSO_WINDOW_BDS_NUM - nbds_in_hdr;
3214b1c4d096SDavid C Somayajulu 
3215b1c4d096SDavid C Somayajulu         nsegs = nsegs - i;
3216b1c4d096SDavid C Somayajulu 
3217b1c4d096SDavid C Somayajulu         while (nsegs >= window) {
321811e25f0dSDavid C Somayajulu                 sum = 0;
3219b1c4d096SDavid C Somayajulu                 s_seg = segs;
322011e25f0dSDavid C Somayajulu 
3221b1c4d096SDavid C Somayajulu                 for (i = 0; i < window; i++){
3222b1c4d096SDavid C Somayajulu                         sum += s_seg->ds_len;
3223b1c4d096SDavid C Somayajulu                         s_seg++;
322411e25f0dSDavid C Somayajulu                 }
322511e25f0dSDavid C Somayajulu 
322611e25f0dSDavid C Somayajulu                 if (sum < ETH_TX_LSO_WINDOW_MIN_LEN) {
322711e25f0dSDavid C Somayajulu                         fp->tx_lso_wnd_min_len++;
322811e25f0dSDavid C Somayajulu                         return (-1);
322911e25f0dSDavid C Somayajulu                 }
323011e25f0dSDavid C Somayajulu 
3231b1c4d096SDavid C Somayajulu                 nsegs = nsegs - 1;
3232b1c4d096SDavid C Somayajulu                 segs++;
323311e25f0dSDavid C Somayajulu         }
323411e25f0dSDavid C Somayajulu 
323511e25f0dSDavid C Somayajulu 	return (0);
323611e25f0dSDavid C Somayajulu }
323711e25f0dSDavid C Somayajulu 
323811e25f0dSDavid C Somayajulu static int
qlnx_send(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct mbuf ** m_headp)323911e25f0dSDavid C Somayajulu qlnx_send(qlnx_host_t *ha, struct qlnx_fastpath *fp, struct mbuf **m_headp)
324011e25f0dSDavid C Somayajulu {
324111e25f0dSDavid C Somayajulu 	bus_dma_segment_t	*segs;
324211e25f0dSDavid C Somayajulu 	bus_dmamap_t		map = 0;
324311e25f0dSDavid C Somayajulu 	uint32_t		nsegs = 0;
324411e25f0dSDavid C Somayajulu 	int			ret = -1;
324511e25f0dSDavid C Somayajulu 	struct mbuf		*m_head = *m_headp;
324611e25f0dSDavid C Somayajulu 	uint16_t		idx = 0;
324711e25f0dSDavid C Somayajulu 	uint16_t		elem_left;
324811e25f0dSDavid C Somayajulu 
324911e25f0dSDavid C Somayajulu 	uint8_t			nbd = 0;
325011e25f0dSDavid C Somayajulu 	struct qlnx_tx_queue    *txq;
325111e25f0dSDavid C Somayajulu 
325211e25f0dSDavid C Somayajulu 	struct eth_tx_1st_bd    *first_bd;
325311e25f0dSDavid C Somayajulu 	struct eth_tx_2nd_bd    *second_bd;
325411e25f0dSDavid C Somayajulu 	struct eth_tx_3rd_bd    *third_bd;
325511e25f0dSDavid C Somayajulu 	struct eth_tx_bd        *tx_data_bd;
325611e25f0dSDavid C Somayajulu 
325711e25f0dSDavid C Somayajulu 	int			seg_idx = 0;
325811e25f0dSDavid C Somayajulu 	uint32_t		nbds_in_hdr = 0;
325911e25f0dSDavid C Somayajulu 	uint32_t		offset = 0;
326011e25f0dSDavid C Somayajulu 
326145f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
326245f13123SDavid C Somayajulu         uint16_t                bd_used;
326345f13123SDavid C Somayajulu #endif
326445f13123SDavid C Somayajulu 
3265217ec208SDavid C Somayajulu 	QL_DPRINT8(ha, "enter[%d]\n", fp->rss_id);
326611e25f0dSDavid C Somayajulu 
326711e25f0dSDavid C Somayajulu 	if (!ha->link_up)
326811e25f0dSDavid C Somayajulu 		return (-1);
326911e25f0dSDavid C Somayajulu 
327011e25f0dSDavid C Somayajulu 	first_bd	= NULL;
327111e25f0dSDavid C Somayajulu 	second_bd	= NULL;
327211e25f0dSDavid C Somayajulu 	third_bd	= NULL;
327311e25f0dSDavid C Somayajulu 	tx_data_bd	= NULL;
327411e25f0dSDavid C Somayajulu 
327511e25f0dSDavid C Somayajulu 	txq = fp->txq[0];
327677388ed2SDavid C Somayajulu 
327745f13123SDavid C Somayajulu         if ((int)(elem_left = ecore_chain_get_elem_left(&txq->tx_pbl)) <
327845f13123SDavid C Somayajulu 		QLNX_TX_ELEM_MIN_THRESH) {
327945f13123SDavid C Somayajulu                 fp->tx_nsegs_gt_elem_left++;
328045f13123SDavid C Somayajulu                 fp->err_tx_nsegs_gt_elem_left++;
328145f13123SDavid C Somayajulu 
328245f13123SDavid C Somayajulu                 return (ENOBUFS);
328377388ed2SDavid C Somayajulu         }
328477388ed2SDavid C Somayajulu 
328511e25f0dSDavid C Somayajulu 	idx = txq->sw_tx_prod;
328611e25f0dSDavid C Somayajulu 
328711e25f0dSDavid C Somayajulu 	map = txq->sw_tx_ring[idx].map;
328811e25f0dSDavid C Somayajulu 	segs = txq->segs;
328911e25f0dSDavid C Somayajulu 
329011e25f0dSDavid C Somayajulu 	ret = bus_dmamap_load_mbuf_sg(ha->tx_tag, map, m_head, segs, &nsegs,
329111e25f0dSDavid C Somayajulu 			BUS_DMA_NOWAIT);
329211e25f0dSDavid C Somayajulu 
329377388ed2SDavid C Somayajulu 	if (ha->dbg_trace_tso_pkt_len) {
329445f13123SDavid C Somayajulu 		if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
329511e25f0dSDavid C Somayajulu 			if (!fp->tx_tso_min_pkt_len) {
329611e25f0dSDavid C Somayajulu 				fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
329711e25f0dSDavid C Somayajulu 				fp->tx_tso_min_pkt_len = m_head->m_pkthdr.len;
329811e25f0dSDavid C Somayajulu 			} else {
329911e25f0dSDavid C Somayajulu 				if (fp->tx_tso_min_pkt_len > m_head->m_pkthdr.len)
330045f13123SDavid C Somayajulu 					fp->tx_tso_min_pkt_len =
330145f13123SDavid C Somayajulu 						m_head->m_pkthdr.len;
330211e25f0dSDavid C Somayajulu 				if (fp->tx_tso_max_pkt_len < m_head->m_pkthdr.len)
330345f13123SDavid C Somayajulu 					fp->tx_tso_max_pkt_len =
330445f13123SDavid C Somayajulu 						m_head->m_pkthdr.len;
330545f13123SDavid C Somayajulu 			}
330611e25f0dSDavid C Somayajulu 		}
330777388ed2SDavid C Somayajulu 	}
330811e25f0dSDavid C Somayajulu 
330911e25f0dSDavid C Somayajulu 	if (m_head->m_pkthdr.csum_flags & CSUM_TSO)
331011e25f0dSDavid C Somayajulu 		offset = qlnx_tcp_offset(ha, m_head);
331111e25f0dSDavid C Somayajulu 
331211e25f0dSDavid C Somayajulu 	if ((ret == EFBIG) ||
331311e25f0dSDavid C Somayajulu 		((nsegs > QLNX_MAX_SEGMENTS_NON_TSO) && (
331411e25f0dSDavid C Somayajulu 			(!(m_head->m_pkthdr.csum_flags & CSUM_TSO)) ||
331511e25f0dSDavid C Somayajulu 		((m_head->m_pkthdr.csum_flags & CSUM_TSO) &&
331611e25f0dSDavid C Somayajulu 			qlnx_tso_check(fp, segs, nsegs, offset))))) {
331711e25f0dSDavid C Somayajulu 		struct mbuf *m;
331811e25f0dSDavid C Somayajulu 
33197a377fbeSDavid C Somayajulu 		QL_DPRINT8(ha, "EFBIG [%d]\n", m_head->m_pkthdr.len);
332011e25f0dSDavid C Somayajulu 
332111e25f0dSDavid C Somayajulu 		fp->tx_defrag++;
332211e25f0dSDavid C Somayajulu 
332311e25f0dSDavid C Somayajulu 		m = m_defrag(m_head, M_NOWAIT);
332411e25f0dSDavid C Somayajulu 		if (m == NULL) {
332511e25f0dSDavid C Somayajulu 			fp->err_tx_defrag++;
332611e25f0dSDavid C Somayajulu 			fp->tx_pkts_freed++;
332711e25f0dSDavid C Somayajulu 			m_freem(m_head);
332811e25f0dSDavid C Somayajulu 			*m_headp = NULL;
33297a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "m_defrag() = NULL [%d]\n", ret);
333011e25f0dSDavid C Somayajulu 			return (ENOBUFS);
333111e25f0dSDavid C Somayajulu 		}
333211e25f0dSDavid C Somayajulu 
333311e25f0dSDavid C Somayajulu 		m_head = m;
333411e25f0dSDavid C Somayajulu 		*m_headp = m_head;
333511e25f0dSDavid C Somayajulu 
333611e25f0dSDavid C Somayajulu 		if ((ret = bus_dmamap_load_mbuf_sg(ha->tx_tag, map, m_head,
333711e25f0dSDavid C Somayajulu 				segs, &nsegs, BUS_DMA_NOWAIT))) {
333811e25f0dSDavid C Somayajulu 			fp->err_tx_defrag_dmamap_load++;
333911e25f0dSDavid C Somayajulu 
33407a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha,
33417a377fbeSDavid C Somayajulu 				"bus_dmamap_load_mbuf_sg failed0 [%d, %d]\n",
33427a377fbeSDavid C Somayajulu 				ret, m_head->m_pkthdr.len);
334311e25f0dSDavid C Somayajulu 
334411e25f0dSDavid C Somayajulu 			fp->tx_pkts_freed++;
334511e25f0dSDavid C Somayajulu 			m_freem(m_head);
334611e25f0dSDavid C Somayajulu 			*m_headp = NULL;
334711e25f0dSDavid C Somayajulu 
334811e25f0dSDavid C Somayajulu 			return (ret);
334911e25f0dSDavid C Somayajulu 		}
335011e25f0dSDavid C Somayajulu 
335111e25f0dSDavid C Somayajulu 		if ((nsegs > QLNX_MAX_SEGMENTS_NON_TSO) &&
335211e25f0dSDavid C Somayajulu 			!(m_head->m_pkthdr.csum_flags & CSUM_TSO)) {
335311e25f0dSDavid C Somayajulu 			fp->err_tx_non_tso_max_seg++;
335411e25f0dSDavid C Somayajulu 
33557a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha,
33567a377fbeSDavid C Somayajulu 				"(%d) nsegs too many for non-TSO [%d, %d]\n",
33577a377fbeSDavid C Somayajulu 				ret, nsegs, m_head->m_pkthdr.len);
335811e25f0dSDavid C Somayajulu 
335911e25f0dSDavid C Somayajulu 			fp->tx_pkts_freed++;
336011e25f0dSDavid C Somayajulu 			m_freem(m_head);
336111e25f0dSDavid C Somayajulu 			*m_headp = NULL;
336211e25f0dSDavid C Somayajulu 
336311e25f0dSDavid C Somayajulu 			return (ret);
336411e25f0dSDavid C Somayajulu 		}
336511e25f0dSDavid C Somayajulu 		if (m_head->m_pkthdr.csum_flags & CSUM_TSO)
336611e25f0dSDavid C Somayajulu 			offset = qlnx_tcp_offset(ha, m_head);
336711e25f0dSDavid C Somayajulu 
336811e25f0dSDavid C Somayajulu 	} else if (ret) {
336911e25f0dSDavid C Somayajulu 		fp->err_tx_dmamap_load++;
337011e25f0dSDavid C Somayajulu 
33717a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "bus_dmamap_load_mbuf_sg failed1 [%d, %d]\n",
33727a377fbeSDavid C Somayajulu 			   ret, m_head->m_pkthdr.len);
337311e25f0dSDavid C Somayajulu 		fp->tx_pkts_freed++;
337411e25f0dSDavid C Somayajulu 		m_freem(m_head);
337511e25f0dSDavid C Somayajulu 		*m_headp = NULL;
337611e25f0dSDavid C Somayajulu 		return (ret);
337711e25f0dSDavid C Somayajulu 	}
337811e25f0dSDavid C Somayajulu 
337911e25f0dSDavid C Somayajulu 	QL_ASSERT(ha, (nsegs != 0), ("qlnx_send: empty packet"));
338011e25f0dSDavid C Somayajulu 
338177388ed2SDavid C Somayajulu 	if (ha->dbg_trace_tso_pkt_len) {
338211e25f0dSDavid C Somayajulu 		if (nsegs < QLNX_FP_MAX_SEGS)
338311e25f0dSDavid C Somayajulu 			fp->tx_pkts[(nsegs - 1)]++;
338411e25f0dSDavid C Somayajulu 		else
338511e25f0dSDavid C Somayajulu 			fp->tx_pkts[(QLNX_FP_MAX_SEGS - 1)]++;
338677388ed2SDavid C Somayajulu 	}
338711e25f0dSDavid C Somayajulu 
338845f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
338945f13123SDavid C Somayajulu         if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
339045f13123SDavid C Somayajulu                 if(m_head->m_pkthdr.len <= 2048)
339145f13123SDavid C Somayajulu                         fp->tx_pkts_hist[0]++;
339245f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 2048) &&
339345f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 4096))
339445f13123SDavid C Somayajulu                         fp->tx_pkts_hist[1]++;
339545f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 4096) &&
339645f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 8192))
339745f13123SDavid C Somayajulu                         fp->tx_pkts_hist[2]++;
339845f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 8192) &&
339945f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 12288 ))
340045f13123SDavid C Somayajulu                         fp->tx_pkts_hist[3]++;
340145f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 11288) &&
340245f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 16394))
340345f13123SDavid C Somayajulu                         fp->tx_pkts_hist[4]++;
340445f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 16384) &&
340545f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 20480))
340645f13123SDavid C Somayajulu                         fp->tx_pkts_hist[5]++;
340745f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 20480) &&
340845f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 24576))
340945f13123SDavid C Somayajulu                         fp->tx_pkts_hist[6]++;
341045f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 24576) &&
341145f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 28672))
341245f13123SDavid C Somayajulu                         fp->tx_pkts_hist[7]++;
341345f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 28762) &&
341445f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 32768))
341545f13123SDavid C Somayajulu                         fp->tx_pkts_hist[8]++;
341645f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 32768) &&
341745f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 36864))
341845f13123SDavid C Somayajulu                         fp->tx_pkts_hist[9]++;
341945f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 36864) &&
342045f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 40960))
342145f13123SDavid C Somayajulu                         fp->tx_pkts_hist[10]++;
342245f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 40960) &&
342345f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 45056))
342445f13123SDavid C Somayajulu                         fp->tx_pkts_hist[11]++;
342545f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 45056) &&
342645f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 49152))
342745f13123SDavid C Somayajulu                         fp->tx_pkts_hist[12]++;
342845f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 49512) &&
342945f13123SDavid C Somayajulu 				m_head->m_pkthdr.len <= 53248))
343045f13123SDavid C Somayajulu                         fp->tx_pkts_hist[13]++;
343145f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 53248) &&
343245f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 57344))
343345f13123SDavid C Somayajulu                         fp->tx_pkts_hist[14]++;
343445f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 53248) &&
343545f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 57344))
343645f13123SDavid C Somayajulu                         fp->tx_pkts_hist[15]++;
343745f13123SDavid C Somayajulu                 else if((m_head->m_pkthdr.len > 57344) &&
343845f13123SDavid C Somayajulu 				(m_head->m_pkthdr.len <= 61440))
343945f13123SDavid C Somayajulu                         fp->tx_pkts_hist[16]++;
344045f13123SDavid C Somayajulu                 else
344145f13123SDavid C Somayajulu                         fp->tx_pkts_hist[17]++;
344245f13123SDavid C Somayajulu         }
344345f13123SDavid C Somayajulu 
344445f13123SDavid C Somayajulu         if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
344545f13123SDavid C Somayajulu                 elem_left =  ecore_chain_get_elem_left(&txq->tx_pbl);
344645f13123SDavid C Somayajulu                 bd_used = TX_RING_SIZE - elem_left;
344745f13123SDavid C Somayajulu 
344845f13123SDavid C Somayajulu                 if(bd_used <= 100)
344945f13123SDavid C Somayajulu                         fp->tx_pkts_q[0]++;
345045f13123SDavid C Somayajulu                 else if((bd_used > 100) && (bd_used <= 500))
345145f13123SDavid C Somayajulu                         fp->tx_pkts_q[1]++;
345245f13123SDavid C Somayajulu                 else if((bd_used > 500) && (bd_used <= 1000))
345345f13123SDavid C Somayajulu                         fp->tx_pkts_q[2]++;
345445f13123SDavid C Somayajulu                 else if((bd_used > 1000) && (bd_used <= 2000))
345545f13123SDavid C Somayajulu                         fp->tx_pkts_q[3]++;
345645f13123SDavid C Somayajulu                 else if((bd_used > 3000) && (bd_used <= 4000))
345745f13123SDavid C Somayajulu                         fp->tx_pkts_q[4]++;
345845f13123SDavid C Somayajulu                 else if((bd_used > 4000) && (bd_used <= 5000))
345945f13123SDavid C Somayajulu                         fp->tx_pkts_q[5]++;
346045f13123SDavid C Somayajulu                 else if((bd_used > 6000) && (bd_used <= 7000))
346145f13123SDavid C Somayajulu                         fp->tx_pkts_q[6]++;
346245f13123SDavid C Somayajulu                 else if((bd_used > 7000) && (bd_used <= 8000))
346345f13123SDavid C Somayajulu                         fp->tx_pkts_q[7]++;
346445f13123SDavid C Somayajulu                 else if((bd_used > 8000) && (bd_used <= 9000))
346545f13123SDavid C Somayajulu                         fp->tx_pkts_q[8]++;
346645f13123SDavid C Somayajulu                 else if((bd_used > 9000) && (bd_used <= 10000))
346745f13123SDavid C Somayajulu                         fp->tx_pkts_q[9]++;
346845f13123SDavid C Somayajulu                 else if((bd_used > 10000) && (bd_used <= 11000))
346945f13123SDavid C Somayajulu                         fp->tx_pkts_q[10]++;
347045f13123SDavid C Somayajulu                 else if((bd_used > 11000) && (bd_used <= 12000))
347145f13123SDavid C Somayajulu                         fp->tx_pkts_q[11]++;
347245f13123SDavid C Somayajulu                 else if((bd_used > 12000) && (bd_used <= 13000))
347345f13123SDavid C Somayajulu                         fp->tx_pkts_q[12]++;
347445f13123SDavid C Somayajulu                 else if((bd_used > 13000) && (bd_used <= 14000))
347545f13123SDavid C Somayajulu                         fp->tx_pkts_q[13]++;
347645f13123SDavid C Somayajulu                 else if((bd_used > 14000) && (bd_used <= 15000))
347745f13123SDavid C Somayajulu                         fp->tx_pkts_q[14]++;
347845f13123SDavid C Somayajulu                else if((bd_used > 15000) && (bd_used <= 16000))
347945f13123SDavid C Somayajulu                         fp->tx_pkts_q[15]++;
348045f13123SDavid C Somayajulu                 else
348145f13123SDavid C Somayajulu                         fp->tx_pkts_q[16]++;
348245f13123SDavid C Somayajulu         }
348345f13123SDavid C Somayajulu 
348445f13123SDavid C Somayajulu #endif /* end of QLNX_TRACE_PERF_DATA */
348545f13123SDavid C Somayajulu 
348611e25f0dSDavid C Somayajulu 	if ((nsegs + QLNX_TX_ELEM_RESERVE) >
348711e25f0dSDavid C Somayajulu 		(int)(elem_left = ecore_chain_get_elem_left(&txq->tx_pbl))) {
34887a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "(%d, 0x%x) insuffient BDs"
348911e25f0dSDavid C Somayajulu 			" in chain[%d] trying to free packets\n",
34907a377fbeSDavid C Somayajulu 			nsegs, elem_left, fp->rss_id);
349111e25f0dSDavid C Somayajulu 
349211e25f0dSDavid C Somayajulu 		fp->tx_nsegs_gt_elem_left++;
349311e25f0dSDavid C Somayajulu 
349411e25f0dSDavid C Somayajulu 		(void)qlnx_tx_int(ha, fp, txq);
349511e25f0dSDavid C Somayajulu 
349611e25f0dSDavid C Somayajulu 		if ((nsegs + QLNX_TX_ELEM_RESERVE) > (int)(elem_left =
349711e25f0dSDavid C Somayajulu 			ecore_chain_get_elem_left(&txq->tx_pbl))) {
34987a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha,
34997a377fbeSDavid C Somayajulu 				"(%d, 0x%x) insuffient BDs in chain[%d]\n",
35007a377fbeSDavid C Somayajulu 				nsegs, elem_left, fp->rss_id);
350111e25f0dSDavid C Somayajulu 
350211e25f0dSDavid C Somayajulu 			fp->err_tx_nsegs_gt_elem_left++;
350377388ed2SDavid C Somayajulu 			fp->tx_ring_full = 1;
350445f13123SDavid C Somayajulu 			if (ha->storm_stats_enable)
350545f13123SDavid C Somayajulu 				ha->storm_stats_gather = 1;
350611e25f0dSDavid C Somayajulu 			return (ENOBUFS);
350711e25f0dSDavid C Somayajulu 		}
350811e25f0dSDavid C Somayajulu 	}
350911e25f0dSDavid C Somayajulu 
351011e25f0dSDavid C Somayajulu 	bus_dmamap_sync(ha->tx_tag, map, BUS_DMASYNC_PREWRITE);
351111e25f0dSDavid C Somayajulu 
351211e25f0dSDavid C Somayajulu 	txq->sw_tx_ring[idx].mp = m_head;
351311e25f0dSDavid C Somayajulu 
351411e25f0dSDavid C Somayajulu 	first_bd = (struct eth_tx_1st_bd *)ecore_chain_produce(&txq->tx_pbl);
351511e25f0dSDavid C Somayajulu 
351611e25f0dSDavid C Somayajulu 	memset(first_bd, 0, sizeof(*first_bd));
351711e25f0dSDavid C Somayajulu 
351811e25f0dSDavid C Somayajulu 	first_bd->data.bd_flags.bitfields =
351911e25f0dSDavid C Somayajulu 		1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
352011e25f0dSDavid C Somayajulu 
352111e25f0dSDavid C Somayajulu 	BD_SET_UNMAP_ADDR_LEN(first_bd, segs->ds_addr, segs->ds_len);
352211e25f0dSDavid C Somayajulu 
352311e25f0dSDavid C Somayajulu 	nbd++;
352411e25f0dSDavid C Somayajulu 
352511e25f0dSDavid C Somayajulu 	if (m_head->m_pkthdr.csum_flags & CSUM_IP) {
352611e25f0dSDavid C Somayajulu 		first_bd->data.bd_flags.bitfields |=
352711e25f0dSDavid C Somayajulu 			(1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT);
352811e25f0dSDavid C Somayajulu 	}
352911e25f0dSDavid C Somayajulu 
35309f4ec086SDavid C Somayajulu 	if (m_head->m_pkthdr.csum_flags &
35319f4ec086SDavid C Somayajulu 		(CSUM_UDP | CSUM_TCP | CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) {
353211e25f0dSDavid C Somayajulu 		first_bd->data.bd_flags.bitfields |=
353311e25f0dSDavid C Somayajulu 			(1 << ETH_TX_1ST_BD_FLAGS_L4_CSUM_SHIFT);
353411e25f0dSDavid C Somayajulu 	}
353511e25f0dSDavid C Somayajulu 
353611e25f0dSDavid C Somayajulu         if (m_head->m_flags & M_VLANTAG) {
353711e25f0dSDavid C Somayajulu                 first_bd->data.vlan = m_head->m_pkthdr.ether_vtag;
353811e25f0dSDavid C Somayajulu 		first_bd->data.bd_flags.bitfields |=
353911e25f0dSDavid C Somayajulu 			(1 << ETH_TX_1ST_BD_FLAGS_VLAN_INSERTION_SHIFT);
354011e25f0dSDavid C Somayajulu         }
354111e25f0dSDavid C Somayajulu 
354211e25f0dSDavid C Somayajulu 	if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
354311e25f0dSDavid C Somayajulu                 first_bd->data.bd_flags.bitfields |=
354411e25f0dSDavid C Somayajulu 			(1 << ETH_TX_1ST_BD_FLAGS_LSO_SHIFT);
354511e25f0dSDavid C Somayajulu 		first_bd->data.bd_flags.bitfields |=
354611e25f0dSDavid C Somayajulu 			(1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT);
354711e25f0dSDavid C Somayajulu 
354811e25f0dSDavid C Somayajulu 		nbds_in_hdr = 1;
354911e25f0dSDavid C Somayajulu 
355011e25f0dSDavid C Somayajulu 		if (offset == segs->ds_len) {
355111e25f0dSDavid C Somayajulu 			BD_SET_UNMAP_ADDR_LEN(first_bd, segs->ds_addr, offset);
355211e25f0dSDavid C Somayajulu 			segs++;
355311e25f0dSDavid C Somayajulu 			seg_idx++;
355411e25f0dSDavid C Somayajulu 
355511e25f0dSDavid C Somayajulu 			second_bd = (struct eth_tx_2nd_bd *)
355611e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
355711e25f0dSDavid C Somayajulu 			memset(second_bd, 0, sizeof(*second_bd));
355811e25f0dSDavid C Somayajulu 			nbd++;
355911e25f0dSDavid C Somayajulu 
356011e25f0dSDavid C Somayajulu 			if (seg_idx < nsegs) {
356111e25f0dSDavid C Somayajulu 				BD_SET_UNMAP_ADDR_LEN(second_bd, \
356211e25f0dSDavid C Somayajulu 					(segs->ds_addr), (segs->ds_len));
356311e25f0dSDavid C Somayajulu 				segs++;
356411e25f0dSDavid C Somayajulu 				seg_idx++;
356511e25f0dSDavid C Somayajulu 			}
356611e25f0dSDavid C Somayajulu 
356711e25f0dSDavid C Somayajulu 			third_bd = (struct eth_tx_3rd_bd *)
356811e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
356911e25f0dSDavid C Somayajulu 			memset(third_bd, 0, sizeof(*third_bd));
357011e25f0dSDavid C Somayajulu 			third_bd->data.lso_mss = m_head->m_pkthdr.tso_segsz;
357111e25f0dSDavid C Somayajulu 			third_bd->data.bitfields |=
357211e25f0dSDavid C Somayajulu 				(nbds_in_hdr<<ETH_TX_DATA_3RD_BD_HDR_NBD_SHIFT);
357311e25f0dSDavid C Somayajulu 			nbd++;
357411e25f0dSDavid C Somayajulu 
357511e25f0dSDavid C Somayajulu 			if (seg_idx < nsegs) {
357611e25f0dSDavid C Somayajulu 				BD_SET_UNMAP_ADDR_LEN(third_bd, \
357711e25f0dSDavid C Somayajulu 					(segs->ds_addr), (segs->ds_len));
357811e25f0dSDavid C Somayajulu 				segs++;
357911e25f0dSDavid C Somayajulu 				seg_idx++;
358011e25f0dSDavid C Somayajulu 			}
358111e25f0dSDavid C Somayajulu 
358211e25f0dSDavid C Somayajulu 			for (; seg_idx < nsegs; seg_idx++) {
358311e25f0dSDavid C Somayajulu 				tx_data_bd = (struct eth_tx_bd *)
358411e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
358511e25f0dSDavid C Somayajulu 				memset(tx_data_bd, 0, sizeof(*tx_data_bd));
358611e25f0dSDavid C Somayajulu 				BD_SET_UNMAP_ADDR_LEN(tx_data_bd, \
358711e25f0dSDavid C Somayajulu 					segs->ds_addr,\
358811e25f0dSDavid C Somayajulu 					segs->ds_len);
358911e25f0dSDavid C Somayajulu 				segs++;
359011e25f0dSDavid C Somayajulu 				nbd++;
359111e25f0dSDavid C Somayajulu 			}
359211e25f0dSDavid C Somayajulu 
359311e25f0dSDavid C Somayajulu 		} else if (offset < segs->ds_len) {
359411e25f0dSDavid C Somayajulu 			BD_SET_UNMAP_ADDR_LEN(first_bd, segs->ds_addr, offset);
359511e25f0dSDavid C Somayajulu 
359611e25f0dSDavid C Somayajulu 			second_bd = (struct eth_tx_2nd_bd *)
359711e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
359811e25f0dSDavid C Somayajulu 			memset(second_bd, 0, sizeof(*second_bd));
359911e25f0dSDavid C Somayajulu 			BD_SET_UNMAP_ADDR_LEN(second_bd, \
360011e25f0dSDavid C Somayajulu 				(segs->ds_addr + offset),\
360111e25f0dSDavid C Somayajulu 				(segs->ds_len - offset));
360211e25f0dSDavid C Somayajulu 			nbd++;
360311e25f0dSDavid C Somayajulu 			segs++;
360411e25f0dSDavid C Somayajulu 
360511e25f0dSDavid C Somayajulu 			third_bd = (struct eth_tx_3rd_bd *)
360611e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
360711e25f0dSDavid C Somayajulu 			memset(third_bd, 0, sizeof(*third_bd));
360811e25f0dSDavid C Somayajulu 
360911e25f0dSDavid C Somayajulu 			BD_SET_UNMAP_ADDR_LEN(third_bd, \
361011e25f0dSDavid C Somayajulu 					segs->ds_addr,\
361111e25f0dSDavid C Somayajulu 					segs->ds_len);
361211e25f0dSDavid C Somayajulu 			third_bd->data.lso_mss = m_head->m_pkthdr.tso_segsz;
361311e25f0dSDavid C Somayajulu 			third_bd->data.bitfields |=
361411e25f0dSDavid C Somayajulu 				(nbds_in_hdr<<ETH_TX_DATA_3RD_BD_HDR_NBD_SHIFT);
361511e25f0dSDavid C Somayajulu 			segs++;
361611e25f0dSDavid C Somayajulu 			nbd++;
361711e25f0dSDavid C Somayajulu 
361811e25f0dSDavid C Somayajulu 			for (seg_idx = 2; seg_idx < nsegs; seg_idx++) {
361911e25f0dSDavid C Somayajulu 				tx_data_bd = (struct eth_tx_bd *)
362011e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
362111e25f0dSDavid C Somayajulu 				memset(tx_data_bd, 0, sizeof(*tx_data_bd));
362211e25f0dSDavid C Somayajulu 				BD_SET_UNMAP_ADDR_LEN(tx_data_bd, \
362311e25f0dSDavid C Somayajulu 					segs->ds_addr,\
362411e25f0dSDavid C Somayajulu 					segs->ds_len);
362511e25f0dSDavid C Somayajulu 				segs++;
362611e25f0dSDavid C Somayajulu 				nbd++;
362711e25f0dSDavid C Somayajulu 			}
362811e25f0dSDavid C Somayajulu 
362911e25f0dSDavid C Somayajulu 		} else {
363011e25f0dSDavid C Somayajulu 			offset = offset - segs->ds_len;
363111e25f0dSDavid C Somayajulu 			segs++;
363211e25f0dSDavid C Somayajulu 
363311e25f0dSDavid C Somayajulu 			for (seg_idx = 1; seg_idx < nsegs; seg_idx++) {
363411e25f0dSDavid C Somayajulu 				if (offset)
363511e25f0dSDavid C Somayajulu 					nbds_in_hdr++;
363611e25f0dSDavid C Somayajulu 
363711e25f0dSDavid C Somayajulu 				tx_data_bd = (struct eth_tx_bd *)
363811e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
363911e25f0dSDavid C Somayajulu 				memset(tx_data_bd, 0, sizeof(*tx_data_bd));
364011e25f0dSDavid C Somayajulu 
364111e25f0dSDavid C Somayajulu 				if (second_bd == NULL) {
364211e25f0dSDavid C Somayajulu 					second_bd = (struct eth_tx_2nd_bd *)
364311e25f0dSDavid C Somayajulu 								tx_data_bd;
364411e25f0dSDavid C Somayajulu 				} else if (third_bd == NULL) {
364511e25f0dSDavid C Somayajulu 					third_bd = (struct eth_tx_3rd_bd *)
364611e25f0dSDavid C Somayajulu 								tx_data_bd;
364711e25f0dSDavid C Somayajulu 				}
364811e25f0dSDavid C Somayajulu 
364911e25f0dSDavid C Somayajulu 				if (offset && (offset < segs->ds_len)) {
365011e25f0dSDavid C Somayajulu 					BD_SET_UNMAP_ADDR_LEN(tx_data_bd,\
365111e25f0dSDavid C Somayajulu 						segs->ds_addr, offset);
365211e25f0dSDavid C Somayajulu 
365311e25f0dSDavid C Somayajulu 					tx_data_bd = (struct eth_tx_bd *)
365411e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
365511e25f0dSDavid C Somayajulu 
365611e25f0dSDavid C Somayajulu 					memset(tx_data_bd, 0,
365711e25f0dSDavid C Somayajulu 						sizeof(*tx_data_bd));
365811e25f0dSDavid C Somayajulu 
365911e25f0dSDavid C Somayajulu 					if (second_bd == NULL) {
366011e25f0dSDavid C Somayajulu 						second_bd =
366111e25f0dSDavid C Somayajulu 					(struct eth_tx_2nd_bd *)tx_data_bd;
366211e25f0dSDavid C Somayajulu 					} else if (third_bd == NULL) {
366311e25f0dSDavid C Somayajulu 						third_bd =
366411e25f0dSDavid C Somayajulu 					(struct eth_tx_3rd_bd *)tx_data_bd;
366511e25f0dSDavid C Somayajulu 					}
366611e25f0dSDavid C Somayajulu 					BD_SET_UNMAP_ADDR_LEN(tx_data_bd,\
366711e25f0dSDavid C Somayajulu 						(segs->ds_addr + offset), \
366811e25f0dSDavid C Somayajulu 						(segs->ds_len - offset));
366911e25f0dSDavid C Somayajulu 					nbd++;
367011e25f0dSDavid C Somayajulu 					offset = 0;
367111e25f0dSDavid C Somayajulu 				} else {
367211e25f0dSDavid C Somayajulu 					if (offset)
367311e25f0dSDavid C Somayajulu 						offset = offset - segs->ds_len;
367411e25f0dSDavid C Somayajulu 					BD_SET_UNMAP_ADDR_LEN(tx_data_bd,\
367511e25f0dSDavid C Somayajulu 						segs->ds_addr, segs->ds_len);
367611e25f0dSDavid C Somayajulu 				}
367711e25f0dSDavid C Somayajulu 				segs++;
367811e25f0dSDavid C Somayajulu 				nbd++;
367911e25f0dSDavid C Somayajulu 			}
368011e25f0dSDavid C Somayajulu 
368111e25f0dSDavid C Somayajulu 			if (third_bd == NULL) {
368211e25f0dSDavid C Somayajulu 				third_bd = (struct eth_tx_3rd_bd *)
368311e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
368411e25f0dSDavid C Somayajulu 				memset(third_bd, 0, sizeof(*third_bd));
368511e25f0dSDavid C Somayajulu 			}
368611e25f0dSDavid C Somayajulu 
368711e25f0dSDavid C Somayajulu 			third_bd->data.lso_mss = m_head->m_pkthdr.tso_segsz;
368811e25f0dSDavid C Somayajulu 			third_bd->data.bitfields |=
368911e25f0dSDavid C Somayajulu 				(nbds_in_hdr<<ETH_TX_DATA_3RD_BD_HDR_NBD_SHIFT);
369011e25f0dSDavid C Somayajulu 		}
369145f13123SDavid C Somayajulu 		fp->tx_tso_pkts++;
369211e25f0dSDavid C Somayajulu 	} else {
369311e25f0dSDavid C Somayajulu 		segs++;
369411e25f0dSDavid C Somayajulu 		for (seg_idx = 1; seg_idx < nsegs; seg_idx++) {
369511e25f0dSDavid C Somayajulu 			tx_data_bd = (struct eth_tx_bd *)
369611e25f0dSDavid C Somayajulu 					ecore_chain_produce(&txq->tx_pbl);
369711e25f0dSDavid C Somayajulu 			memset(tx_data_bd, 0, sizeof(*tx_data_bd));
369811e25f0dSDavid C Somayajulu 			BD_SET_UNMAP_ADDR_LEN(tx_data_bd, segs->ds_addr,\
369911e25f0dSDavid C Somayajulu 				segs->ds_len);
370011e25f0dSDavid C Somayajulu 			segs++;
370111e25f0dSDavid C Somayajulu 			nbd++;
370211e25f0dSDavid C Somayajulu 		}
370311e25f0dSDavid C Somayajulu 		first_bd->data.bitfields =
370411e25f0dSDavid C Somayajulu 			(m_head->m_pkthdr.len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK)
370511e25f0dSDavid C Somayajulu 				 << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT;
370611e25f0dSDavid C Somayajulu 		first_bd->data.bitfields =
370711e25f0dSDavid C Somayajulu 			htole16(first_bd->data.bitfields);
370845f13123SDavid C Somayajulu 		fp->tx_non_tso_pkts++;
370911e25f0dSDavid C Somayajulu 	}
371011e25f0dSDavid C Somayajulu 
371111e25f0dSDavid C Somayajulu 	first_bd->data.nbds = nbd;
371211e25f0dSDavid C Somayajulu 
371377388ed2SDavid C Somayajulu 	if (ha->dbg_trace_tso_pkt_len) {
371411e25f0dSDavid C Somayajulu 		if (fp->tx_tso_max_nsegs < nsegs)
371511e25f0dSDavid C Somayajulu 			fp->tx_tso_max_nsegs = nsegs;
371611e25f0dSDavid C Somayajulu 
371711e25f0dSDavid C Somayajulu 		if ((nsegs < fp->tx_tso_min_nsegs) || (!fp->tx_tso_min_nsegs))
371811e25f0dSDavid C Somayajulu 			fp->tx_tso_min_nsegs = nsegs;
371977388ed2SDavid C Somayajulu 	}
372011e25f0dSDavid C Somayajulu 
372111e25f0dSDavid C Somayajulu 	txq->sw_tx_ring[idx].nsegs = nsegs;
372211e25f0dSDavid C Somayajulu 	txq->sw_tx_prod = (txq->sw_tx_prod + 1) & (TX_RING_SIZE - 1);
372311e25f0dSDavid C Somayajulu 
372411e25f0dSDavid C Somayajulu 	txq->tx_db.data.bd_prod =
372511e25f0dSDavid C Somayajulu 		htole16(ecore_chain_get_prod_idx(&txq->tx_pbl));
372611e25f0dSDavid C Somayajulu 
372711e25f0dSDavid C Somayajulu 	qlnx_txq_doorbell_wr32(ha, txq->doorbell_addr, txq->tx_db.raw);
372811e25f0dSDavid C Somayajulu 
3729217ec208SDavid C Somayajulu 	QL_DPRINT8(ha, "exit[%d]\n", fp->rss_id);
373011e25f0dSDavid C Somayajulu 	return (0);
373111e25f0dSDavid C Somayajulu }
373211e25f0dSDavid C Somayajulu 
373311e25f0dSDavid C Somayajulu static void
qlnx_stop(qlnx_host_t * ha)373411e25f0dSDavid C Somayajulu qlnx_stop(qlnx_host_t *ha)
373511e25f0dSDavid C Somayajulu {
3736727bfe38SJustin Hibbits 	if_t		ifp = ha->ifp;
373711e25f0dSDavid C Somayajulu 	int		i;
373811e25f0dSDavid C Somayajulu 
3739727bfe38SJustin Hibbits 	if_setdrvflagbits(ifp, 0, (IFF_DRV_OACTIVE | IFF_DRV_RUNNING));
374011e25f0dSDavid C Somayajulu 
374111e25f0dSDavid C Somayajulu 	/*
374211e25f0dSDavid C Somayajulu 	 * We simply lock and unlock each fp->tx_mtx to
374311e25f0dSDavid C Somayajulu 	 * propagate the if_drv_flags
374411e25f0dSDavid C Somayajulu 	 * state to each tx thread
374511e25f0dSDavid C Somayajulu 	 */
37467a377fbeSDavid C Somayajulu         QL_DPRINT1(ha, "QLNX STATE = %d\n",ha->state);
37477a377fbeSDavid C Somayajulu 
374811e25f0dSDavid C Somayajulu 	if (ha->state == QLNX_STATE_OPEN) {
374911e25f0dSDavid C Somayajulu         	for (i = 0; i < ha->num_rss; i++) {
375011e25f0dSDavid C Somayajulu 			struct qlnx_fastpath *fp = &ha->fp_array[i];
375111e25f0dSDavid C Somayajulu 
375211e25f0dSDavid C Somayajulu 			mtx_lock(&fp->tx_mtx);
375311e25f0dSDavid C Somayajulu 			mtx_unlock(&fp->tx_mtx);
375411e25f0dSDavid C Somayajulu 
375511e25f0dSDavid C Somayajulu 			if (fp->fp_taskqueue != NULL)
375611e25f0dSDavid C Somayajulu 				taskqueue_enqueue(fp->fp_taskqueue,
375711e25f0dSDavid C Somayajulu 					&fp->fp_task);
375811e25f0dSDavid C Somayajulu 		}
375911e25f0dSDavid C Somayajulu 	}
3760217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
3761217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
3762217ec208SDavid C Somayajulu 		qlnx_rdma_dev_close(ha);
3763217ec208SDavid C Somayajulu 	}
3764217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
376511e25f0dSDavid C Somayajulu 
376611e25f0dSDavid C Somayajulu 	qlnx_unload(ha);
376711e25f0dSDavid C Somayajulu 
376811e25f0dSDavid C Somayajulu 	return;
376911e25f0dSDavid C Somayajulu }
377011e25f0dSDavid C Somayajulu 
377111e25f0dSDavid C Somayajulu static int
qlnx_get_ifq_snd_maxlen(qlnx_host_t * ha)377211e25f0dSDavid C Somayajulu qlnx_get_ifq_snd_maxlen(qlnx_host_t *ha)
377311e25f0dSDavid C Somayajulu {
377411e25f0dSDavid C Somayajulu         return(TX_RING_SIZE - 1);
377511e25f0dSDavid C Somayajulu }
377611e25f0dSDavid C Somayajulu 
377711e25f0dSDavid C Somayajulu uint8_t *
qlnx_get_mac_addr(qlnx_host_t * ha)377811e25f0dSDavid C Somayajulu qlnx_get_mac_addr(qlnx_host_t *ha)
377911e25f0dSDavid C Somayajulu {
378011e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
3781217ec208SDavid C Somayajulu 	unsigned char mac[ETHER_ADDR_LEN];
3782217ec208SDavid C Somayajulu 	uint8_t			p_is_forced;
378311e25f0dSDavid C Somayajulu 
378411e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
3785217ec208SDavid C Somayajulu 
3786217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0)
378711e25f0dSDavid C Somayajulu 		return (p_hwfn->hw_info.hw_mac_addr);
3788217ec208SDavid C Somayajulu 
3789217ec208SDavid C Somayajulu 	ecore_vf_read_bulletin(p_hwfn, &p_is_forced);
3790217ec208SDavid C Somayajulu 	if (ecore_vf_bulletin_get_forced_mac(p_hwfn, mac, &p_is_forced) ==
3791217ec208SDavid C Somayajulu 		true) {
3792217ec208SDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: p_is_forced = %d"
3793217ec208SDavid C Somayajulu 			" mac_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", __func__,
3794217ec208SDavid C Somayajulu 			p_is_forced, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
3795217ec208SDavid C Somayajulu         	memcpy(ha->primary_mac, mac, ETH_ALEN);
3796217ec208SDavid C Somayajulu 	}
3797217ec208SDavid C Somayajulu 
3798217ec208SDavid C Somayajulu 	return (ha->primary_mac);
379911e25f0dSDavid C Somayajulu }
380011e25f0dSDavid C Somayajulu 
380111e25f0dSDavid C Somayajulu static uint32_t
qlnx_get_optics(qlnx_host_t * ha,struct qlnx_link_output * if_link)380211e25f0dSDavid C Somayajulu qlnx_get_optics(qlnx_host_t *ha, struct qlnx_link_output *if_link)
380311e25f0dSDavid C Somayajulu {
380411e25f0dSDavid C Somayajulu 	uint32_t	ifm_type = 0;
380511e25f0dSDavid C Somayajulu 
380611e25f0dSDavid C Somayajulu 	switch (if_link->media_type) {
380711e25f0dSDavid C Somayajulu 	case MEDIA_MODULE_FIBER:
380811e25f0dSDavid C Somayajulu 	case MEDIA_UNSPECIFIED:
380911e25f0dSDavid C Somayajulu 		if (if_link->speed == (100 * 1000))
381011e25f0dSDavid C Somayajulu 			ifm_type = QLNX_IFM_100G_SR4;
381111e25f0dSDavid C Somayajulu 		else if (if_link->speed == (40 * 1000))
381211e25f0dSDavid C Somayajulu 			ifm_type = IFM_40G_SR4;
381311e25f0dSDavid C Somayajulu 		else if (if_link->speed == (25 * 1000))
381411e25f0dSDavid C Somayajulu 			ifm_type = QLNX_IFM_25G_SR;
38159efd0ba7SDavid C Somayajulu 		else if (if_link->speed == (10 * 1000))
38169efd0ba7SDavid C Somayajulu 			ifm_type = (IFM_10G_LR | IFM_10G_SR);
38179efd0ba7SDavid C Somayajulu 		else if (if_link->speed == (1 * 1000))
38189efd0ba7SDavid C Somayajulu 			ifm_type = (IFM_1000_SX | IFM_1000_LX);
38199efd0ba7SDavid C Somayajulu 
382011e25f0dSDavid C Somayajulu 		break;
382111e25f0dSDavid C Somayajulu 
382211e25f0dSDavid C Somayajulu 	case MEDIA_DA_TWINAX:
382311e25f0dSDavid C Somayajulu 		if (if_link->speed == (100 * 1000))
382411e25f0dSDavid C Somayajulu 			ifm_type = QLNX_IFM_100G_CR4;
382511e25f0dSDavid C Somayajulu 		else if (if_link->speed == (40 * 1000))
382611e25f0dSDavid C Somayajulu 			ifm_type = IFM_40G_CR4;
382711e25f0dSDavid C Somayajulu 		else if (if_link->speed == (25 * 1000))
382811e25f0dSDavid C Somayajulu 			ifm_type = QLNX_IFM_25G_CR;
38299efd0ba7SDavid C Somayajulu 		else if (if_link->speed == (10 * 1000))
38309efd0ba7SDavid C Somayajulu 			ifm_type = IFM_10G_TWINAX;
38319efd0ba7SDavid C Somayajulu 
383211e25f0dSDavid C Somayajulu 		break;
383311e25f0dSDavid C Somayajulu 
383411e25f0dSDavid C Somayajulu 	default :
383511e25f0dSDavid C Somayajulu 		ifm_type = IFM_UNKNOWN;
383611e25f0dSDavid C Somayajulu 		break;
383711e25f0dSDavid C Somayajulu 	}
383811e25f0dSDavid C Somayajulu 	return (ifm_type);
383911e25f0dSDavid C Somayajulu }
384011e25f0dSDavid C Somayajulu 
384111e25f0dSDavid C Somayajulu /*****************************************************************************
384211e25f0dSDavid C Somayajulu  * Interrupt Service Functions
384311e25f0dSDavid C Somayajulu  *****************************************************************************/
384411e25f0dSDavid C Somayajulu 
384511e25f0dSDavid C Somayajulu static int
qlnx_rx_jumbo_chain(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct mbuf * mp_head,uint16_t len)384611e25f0dSDavid C Somayajulu qlnx_rx_jumbo_chain(qlnx_host_t *ha, struct qlnx_fastpath *fp,
384711e25f0dSDavid C Somayajulu 	struct mbuf *mp_head, uint16_t len)
384811e25f0dSDavid C Somayajulu {
384911e25f0dSDavid C Somayajulu 	struct mbuf		*mp, *mpf, *mpl;
385011e25f0dSDavid C Somayajulu 	struct sw_rx_data	*sw_rx_data;
385111e25f0dSDavid C Somayajulu 	struct qlnx_rx_queue	*rxq;
385211e25f0dSDavid C Somayajulu 	uint16_t 		len_in_buffer;
385311e25f0dSDavid C Somayajulu 
385411e25f0dSDavid C Somayajulu 	rxq = fp->rxq;
385511e25f0dSDavid C Somayajulu 	mpf = mpl = mp = NULL;
385611e25f0dSDavid C Somayajulu 
385711e25f0dSDavid C Somayajulu 	while (len) {
385811e25f0dSDavid C Somayajulu         	rxq->sw_rx_cons  = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
385911e25f0dSDavid C Somayajulu 
386011e25f0dSDavid C Somayajulu                 sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_cons];
386111e25f0dSDavid C Somayajulu                 mp = sw_rx_data->data;
386211e25f0dSDavid C Somayajulu 
386311e25f0dSDavid C Somayajulu 		if (mp == NULL) {
38647a377fbeSDavid C Somayajulu                 	QL_DPRINT1(ha, "mp = NULL\n");
386511e25f0dSDavid C Somayajulu 			fp->err_rx_mp_null++;
386611e25f0dSDavid C Somayajulu         		rxq->sw_rx_cons  =
386711e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
386811e25f0dSDavid C Somayajulu 
386911e25f0dSDavid C Somayajulu 			if (mpf != NULL)
387011e25f0dSDavid C Somayajulu 				m_freem(mpf);
387111e25f0dSDavid C Somayajulu 
387211e25f0dSDavid C Somayajulu 			return (-1);
387311e25f0dSDavid C Somayajulu 		}
387411e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->rx_tag, sw_rx_data->map,
387511e25f0dSDavid C Somayajulu 			BUS_DMASYNC_POSTREAD);
387611e25f0dSDavid C Somayajulu 
387711e25f0dSDavid C Somayajulu                 if (qlnx_alloc_rx_buffer(ha, rxq) != 0) {
38787a377fbeSDavid C Somayajulu                         QL_DPRINT1(ha, "New buffer allocation failed, dropping"
38797a377fbeSDavid C Somayajulu 				" incoming packet and reusing its buffer\n");
388011e25f0dSDavid C Somayajulu 
388111e25f0dSDavid C Somayajulu                         qlnx_reuse_rx_data(rxq);
388211e25f0dSDavid C Somayajulu                         fp->err_rx_alloc_errors++;
388311e25f0dSDavid C Somayajulu 
388411e25f0dSDavid C Somayajulu 			if (mpf != NULL)
388511e25f0dSDavid C Somayajulu 				m_freem(mpf);
388611e25f0dSDavid C Somayajulu 
388711e25f0dSDavid C Somayajulu 			return (-1);
388811e25f0dSDavid C Somayajulu 		}
388911e25f0dSDavid C Somayajulu                 ecore_chain_consume(&rxq->rx_bd_ring);
389011e25f0dSDavid C Somayajulu 
389111e25f0dSDavid C Somayajulu 		if (len > rxq->rx_buf_size)
389211e25f0dSDavid C Somayajulu 			len_in_buffer = rxq->rx_buf_size;
389311e25f0dSDavid C Somayajulu 		else
389411e25f0dSDavid C Somayajulu 			len_in_buffer = len;
389511e25f0dSDavid C Somayajulu 
389611e25f0dSDavid C Somayajulu 		len = len - len_in_buffer;
389711e25f0dSDavid C Somayajulu 
389811e25f0dSDavid C Somayajulu 		mp->m_flags &= ~M_PKTHDR;
389911e25f0dSDavid C Somayajulu 		mp->m_next = NULL;
390011e25f0dSDavid C Somayajulu 		mp->m_len = len_in_buffer;
390111e25f0dSDavid C Somayajulu 
390211e25f0dSDavid C Somayajulu 		if (mpf == NULL)
390311e25f0dSDavid C Somayajulu 			mpf = mpl = mp;
390411e25f0dSDavid C Somayajulu 		else {
390511e25f0dSDavid C Somayajulu 			mpl->m_next = mp;
390611e25f0dSDavid C Somayajulu 			mpl = mp;
390711e25f0dSDavid C Somayajulu 		}
390811e25f0dSDavid C Somayajulu 	}
390911e25f0dSDavid C Somayajulu 
391011e25f0dSDavid C Somayajulu 	if (mpf != NULL)
391111e25f0dSDavid C Somayajulu 		mp_head->m_next = mpf;
391211e25f0dSDavid C Somayajulu 
391311e25f0dSDavid C Somayajulu 	return (0);
391411e25f0dSDavid C Somayajulu }
391511e25f0dSDavid C Somayajulu 
391611e25f0dSDavid C Somayajulu static void
qlnx_tpa_start(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_rx_queue * rxq,struct eth_fast_path_rx_tpa_start_cqe * cqe)391711e25f0dSDavid C Somayajulu qlnx_tpa_start(qlnx_host_t *ha,
391811e25f0dSDavid C Somayajulu 	struct qlnx_fastpath *fp,
391911e25f0dSDavid C Somayajulu 	struct qlnx_rx_queue *rxq,
392011e25f0dSDavid C Somayajulu 	struct eth_fast_path_rx_tpa_start_cqe *cqe)
392111e25f0dSDavid C Somayajulu {
392211e25f0dSDavid C Somayajulu 	uint32_t		agg_index;
3923727bfe38SJustin Hibbits         if_t ifp = ha->ifp;
392411e25f0dSDavid C Somayajulu 	struct mbuf		*mp;
392511e25f0dSDavid C Somayajulu 	struct mbuf		*mpf = NULL, *mpl = NULL, *mpc = NULL;
392611e25f0dSDavid C Somayajulu 	struct sw_rx_data	*sw_rx_data;
392711e25f0dSDavid C Somayajulu 	dma_addr_t		addr;
392811e25f0dSDavid C Somayajulu 	bus_dmamap_t		map;
392911e25f0dSDavid C Somayajulu 	struct eth_rx_bd	*rx_bd;
393011e25f0dSDavid C Somayajulu 	int			i;
393111e25f0dSDavid C Somayajulu 	uint8_t			hash_type;
393211e25f0dSDavid C Somayajulu 
393311e25f0dSDavid C Somayajulu 	agg_index = cqe->tpa_agg_index;
393411e25f0dSDavid C Somayajulu 
39357a377fbeSDavid C Somayajulu         QL_DPRINT7(ha, "[rss_id = %d]: enter\n \
39367a377fbeSDavid C Somayajulu                 \t type = 0x%x\n \
39377a377fbeSDavid C Somayajulu                 \t bitfields = 0x%x\n \
39387a377fbeSDavid C Somayajulu                 \t seg_len = 0x%x\n \
39397a377fbeSDavid C Somayajulu                 \t pars_flags = 0x%x\n \
39407a377fbeSDavid C Somayajulu                 \t vlan_tag = 0x%x\n \
39417a377fbeSDavid C Somayajulu                 \t rss_hash = 0x%x\n \
39427a377fbeSDavid C Somayajulu                 \t len_on_first_bd = 0x%x\n \
39437a377fbeSDavid C Somayajulu                 \t placement_offset = 0x%x\n \
39447a377fbeSDavid C Somayajulu                 \t tpa_agg_index = 0x%x\n \
39457a377fbeSDavid C Somayajulu                 \t header_len = 0x%x\n \
39467a377fbeSDavid C Somayajulu                 \t ext_bd_len_list[0] = 0x%x\n \
39477a377fbeSDavid C Somayajulu                 \t ext_bd_len_list[1] = 0x%x\n \
39487a377fbeSDavid C Somayajulu                 \t ext_bd_len_list[2] = 0x%x\n \
39497a377fbeSDavid C Somayajulu                 \t ext_bd_len_list[3] = 0x%x\n \
39507a377fbeSDavid C Somayajulu                 \t ext_bd_len_list[4] = 0x%x\n",
39517a377fbeSDavid C Somayajulu                 fp->rss_id, cqe->type, cqe->bitfields, cqe->seg_len,
395211e25f0dSDavid C Somayajulu                 cqe->pars_flags.flags, cqe->vlan_tag,
395311e25f0dSDavid C Somayajulu                 cqe->rss_hash, cqe->len_on_first_bd, cqe->placement_offset,
395411e25f0dSDavid C Somayajulu                 cqe->tpa_agg_index, cqe->header_len,
395511e25f0dSDavid C Somayajulu                 cqe->ext_bd_len_list[0], cqe->ext_bd_len_list[1],
395611e25f0dSDavid C Somayajulu                 cqe->ext_bd_len_list[2], cqe->ext_bd_len_list[3],
39577a377fbeSDavid C Somayajulu                 cqe->ext_bd_len_list[4]);
395811e25f0dSDavid C Somayajulu 
395911e25f0dSDavid C Somayajulu 	if (agg_index >= ETH_TPA_MAX_AGGS_NUM) {
396011e25f0dSDavid C Somayajulu 		fp->err_rx_tpa_invalid_agg_num++;
396111e25f0dSDavid C Somayajulu 		return;
396211e25f0dSDavid C Somayajulu 	}
396311e25f0dSDavid C Somayajulu 
396411e25f0dSDavid C Somayajulu 	sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_cons];
396511e25f0dSDavid C Somayajulu 	bus_dmamap_sync(ha->rx_tag, sw_rx_data->map, BUS_DMASYNC_POSTREAD);
396611e25f0dSDavid C Somayajulu 	mp = sw_rx_data->data;
396711e25f0dSDavid C Somayajulu 
39687a377fbeSDavid C Somayajulu 	QL_DPRINT7(ha, "[rss_id = %d]: mp = %p \n ", fp->rss_id, mp);
396911e25f0dSDavid C Somayajulu 
397011e25f0dSDavid C Somayajulu 	if (mp == NULL) {
39717a377fbeSDavid C Somayajulu                	QL_DPRINT7(ha, "[%d]: mp = NULL\n", fp->rss_id);
397211e25f0dSDavid C Somayajulu 		fp->err_rx_mp_null++;
397311e25f0dSDavid C Somayajulu        		rxq->sw_rx_cons = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
397411e25f0dSDavid C Somayajulu 
397511e25f0dSDavid C Somayajulu 		return;
397611e25f0dSDavid C Somayajulu 	}
397711e25f0dSDavid C Somayajulu 
397811e25f0dSDavid C Somayajulu 	if ((le16toh(cqe->pars_flags.flags)) & CQE_FLAGS_ERR) {
39797a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: CQE in CONS = %u has error,"
39807a377fbeSDavid C Somayajulu 			" flags = %x, dropping incoming packet\n", fp->rss_id,
39817a377fbeSDavid C Somayajulu 			rxq->sw_rx_cons, le16toh(cqe->pars_flags.flags));
398211e25f0dSDavid C Somayajulu 
398311e25f0dSDavid C Somayajulu 		fp->err_rx_hw_errors++;
398411e25f0dSDavid C Somayajulu 
398511e25f0dSDavid C Somayajulu 		qlnx_reuse_rx_data(rxq);
398611e25f0dSDavid C Somayajulu 
398711e25f0dSDavid C Somayajulu 		QLNX_INC_IERRORS(ifp);
398811e25f0dSDavid C Somayajulu 
398911e25f0dSDavid C Somayajulu 		return;
399011e25f0dSDavid C Somayajulu 	}
399111e25f0dSDavid C Somayajulu 
399211e25f0dSDavid C Somayajulu 	if (qlnx_alloc_rx_buffer(ha, rxq) != 0) {
39937a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: New buffer allocation failed,"
399411e25f0dSDavid C Somayajulu 			" dropping incoming packet and reusing its buffer\n",
39957a377fbeSDavid C Somayajulu 			fp->rss_id);
399611e25f0dSDavid C Somayajulu 
399711e25f0dSDavid C Somayajulu 		fp->err_rx_alloc_errors++;
399811e25f0dSDavid C Somayajulu 		QLNX_INC_IQDROPS(ifp);
399911e25f0dSDavid C Somayajulu 
400011e25f0dSDavid C Somayajulu 		/*
400111e25f0dSDavid C Somayajulu 		 * Load the tpa mbuf into the rx ring and save the
400211e25f0dSDavid C Somayajulu 		 * posted mbuf
400311e25f0dSDavid C Somayajulu 		 */
400411e25f0dSDavid C Somayajulu 
400511e25f0dSDavid C Somayajulu 		map = sw_rx_data->map;
400611e25f0dSDavid C Somayajulu 		addr = sw_rx_data->dma_addr;
400711e25f0dSDavid C Somayajulu 
400811e25f0dSDavid C Somayajulu 		sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_prod];
400911e25f0dSDavid C Somayajulu 
401011e25f0dSDavid C Somayajulu 		sw_rx_data->data = rxq->tpa_info[agg_index].rx_buf.data;
401111e25f0dSDavid C Somayajulu 		sw_rx_data->dma_addr = rxq->tpa_info[agg_index].rx_buf.dma_addr;
401211e25f0dSDavid C Somayajulu 		sw_rx_data->map = rxq->tpa_info[agg_index].rx_buf.map;
401311e25f0dSDavid C Somayajulu 
401411e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].rx_buf.data = mp;
401511e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].rx_buf.dma_addr = addr;
401611e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].rx_buf.map = map;
401711e25f0dSDavid C Somayajulu 
401811e25f0dSDavid C Somayajulu 		rx_bd = (struct eth_rx_bd *)
401911e25f0dSDavid C Somayajulu 				ecore_chain_produce(&rxq->rx_bd_ring);
402011e25f0dSDavid C Somayajulu 
402111e25f0dSDavid C Somayajulu 		rx_bd->addr.hi = htole32(U64_HI(sw_rx_data->dma_addr));
402211e25f0dSDavid C Somayajulu 		rx_bd->addr.lo = htole32(U64_LO(sw_rx_data->dma_addr));
402311e25f0dSDavid C Somayajulu 
402411e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->rx_tag, sw_rx_data->map,
402511e25f0dSDavid C Somayajulu 			BUS_DMASYNC_PREREAD);
402611e25f0dSDavid C Somayajulu 
402711e25f0dSDavid C Somayajulu 		rxq->sw_rx_prod = (rxq->sw_rx_prod + 1) & (RX_RING_SIZE - 1);
402811e25f0dSDavid C Somayajulu 		rxq->sw_rx_cons = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
402911e25f0dSDavid C Somayajulu 
403011e25f0dSDavid C Somayajulu 		ecore_chain_consume(&rxq->rx_bd_ring);
403111e25f0dSDavid C Somayajulu 
403211e25f0dSDavid C Somayajulu 		/* Now reuse any buffers posted in ext_bd_len_list */
403311e25f0dSDavid C Somayajulu 		for (i = 0; i < ETH_TPA_CQE_START_LEN_LIST_SIZE; i++) {
403411e25f0dSDavid C Somayajulu 			if (cqe->ext_bd_len_list[i] == 0)
403511e25f0dSDavid C Somayajulu 				break;
403611e25f0dSDavid C Somayajulu 
403711e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
403811e25f0dSDavid C Somayajulu 		}
403911e25f0dSDavid C Somayajulu 
404011e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].agg_state = QLNX_AGG_STATE_ERROR;
404111e25f0dSDavid C Somayajulu 		return;
404211e25f0dSDavid C Somayajulu 	}
404311e25f0dSDavid C Somayajulu 
404411e25f0dSDavid C Somayajulu 	if (rxq->tpa_info[agg_index].agg_state != QLNX_AGG_STATE_NONE) {
40457a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: invalid aggregation state,"
404611e25f0dSDavid C Somayajulu 			" dropping incoming packet and reusing its buffer\n",
40477a377fbeSDavid C Somayajulu 			fp->rss_id);
404811e25f0dSDavid C Somayajulu 
404911e25f0dSDavid C Somayajulu 		QLNX_INC_IQDROPS(ifp);
405011e25f0dSDavid C Somayajulu 
405111e25f0dSDavid C Somayajulu 		/* if we already have mbuf head in aggregation free it */
405211e25f0dSDavid C Somayajulu 		if (rxq->tpa_info[agg_index].mpf) {
405311e25f0dSDavid C Somayajulu 			m_freem(rxq->tpa_info[agg_index].mpf);
405411e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].mpl = NULL;
405511e25f0dSDavid C Somayajulu 		}
405611e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpf = mp;
405711e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpl = NULL;
405811e25f0dSDavid C Somayajulu 
405911e25f0dSDavid C Somayajulu 		rxq->sw_rx_cons = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
406011e25f0dSDavid C Somayajulu 		ecore_chain_consume(&rxq->rx_bd_ring);
406111e25f0dSDavid C Somayajulu 
406211e25f0dSDavid C Somayajulu 		/* Now reuse any buffers posted in ext_bd_len_list */
406311e25f0dSDavid C Somayajulu 		for (i = 0; i < ETH_TPA_CQE_START_LEN_LIST_SIZE; i++) {
406411e25f0dSDavid C Somayajulu 			if (cqe->ext_bd_len_list[i] == 0)
406511e25f0dSDavid C Somayajulu 				break;
406611e25f0dSDavid C Somayajulu 
406711e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
406811e25f0dSDavid C Somayajulu 		}
406911e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].agg_state = QLNX_AGG_STATE_ERROR;
407011e25f0dSDavid C Somayajulu 
407111e25f0dSDavid C Somayajulu 		return;
407211e25f0dSDavid C Somayajulu 	}
407311e25f0dSDavid C Somayajulu 
407411e25f0dSDavid C Somayajulu 	/*
407511e25f0dSDavid C Somayajulu 	 * first process the ext_bd_len_list
407611e25f0dSDavid C Somayajulu 	 * if this fails then we simply drop the packet
407711e25f0dSDavid C Somayajulu 	 */
407811e25f0dSDavid C Somayajulu 	ecore_chain_consume(&rxq->rx_bd_ring);
407911e25f0dSDavid C Somayajulu 	rxq->sw_rx_cons  = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
408011e25f0dSDavid C Somayajulu 
408111e25f0dSDavid C Somayajulu 	for (i = 0; i < ETH_TPA_CQE_START_LEN_LIST_SIZE; i++) {
40827a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 4\n ", fp->rss_id);
408311e25f0dSDavid C Somayajulu 
408411e25f0dSDavid C Somayajulu 		if (cqe->ext_bd_len_list[i] == 0)
408511e25f0dSDavid C Somayajulu 			break;
408611e25f0dSDavid C Somayajulu 
408711e25f0dSDavid C Somayajulu 		sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_cons];
408811e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->rx_tag, sw_rx_data->map,
408911e25f0dSDavid C Somayajulu 			BUS_DMASYNC_POSTREAD);
409011e25f0dSDavid C Somayajulu 
409111e25f0dSDavid C Somayajulu 		mpc = sw_rx_data->data;
409211e25f0dSDavid C Somayajulu 
409311e25f0dSDavid C Somayajulu 		if (mpc == NULL) {
40947a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: mpc = NULL\n", fp->rss_id);
409511e25f0dSDavid C Somayajulu 			fp->err_rx_mp_null++;
409611e25f0dSDavid C Somayajulu 			if (mpf != NULL)
409711e25f0dSDavid C Somayajulu 				m_freem(mpf);
409811e25f0dSDavid C Somayajulu 			mpf = mpl = NULL;
409911e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].agg_state =
410011e25f0dSDavid C Somayajulu 						QLNX_AGG_STATE_ERROR;
410111e25f0dSDavid C Somayajulu 			ecore_chain_consume(&rxq->rx_bd_ring);
410211e25f0dSDavid C Somayajulu 			rxq->sw_rx_cons =
410311e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
410411e25f0dSDavid C Somayajulu 			continue;
410511e25f0dSDavid C Somayajulu 		}
410611e25f0dSDavid C Somayajulu 
410711e25f0dSDavid C Somayajulu 		if (qlnx_alloc_rx_buffer(ha, rxq) != 0) {
41087a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: New buffer allocation failed,"
41097a377fbeSDavid C Somayajulu 				" dropping incoming packet and reusing its"
41107a377fbeSDavid C Somayajulu 				" buffer\n", fp->rss_id);
411111e25f0dSDavid C Somayajulu 
411211e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
411311e25f0dSDavid C Somayajulu 
411411e25f0dSDavid C Somayajulu 			if (mpf != NULL)
411511e25f0dSDavid C Somayajulu 				m_freem(mpf);
411611e25f0dSDavid C Somayajulu 			mpf = mpl = NULL;
411711e25f0dSDavid C Somayajulu 
411811e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].agg_state =
411911e25f0dSDavid C Somayajulu 						QLNX_AGG_STATE_ERROR;
412011e25f0dSDavid C Somayajulu 
412111e25f0dSDavid C Somayajulu 			ecore_chain_consume(&rxq->rx_bd_ring);
412211e25f0dSDavid C Somayajulu 			rxq->sw_rx_cons =
412311e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
412411e25f0dSDavid C Somayajulu 
412511e25f0dSDavid C Somayajulu 			continue;
412611e25f0dSDavid C Somayajulu 		}
412711e25f0dSDavid C Somayajulu 
412811e25f0dSDavid C Somayajulu 		mpc->m_flags &= ~M_PKTHDR;
412911e25f0dSDavid C Somayajulu 		mpc->m_next = NULL;
413011e25f0dSDavid C Somayajulu 		mpc->m_len = cqe->ext_bd_len_list[i];
413111e25f0dSDavid C Somayajulu 
413211e25f0dSDavid C Somayajulu 		if (mpf == NULL) {
413311e25f0dSDavid C Somayajulu 			mpf = mpl = mpc;
413411e25f0dSDavid C Somayajulu 		} else {
413511e25f0dSDavid C Somayajulu 			mpl->m_len = ha->rx_buf_size;
413611e25f0dSDavid C Somayajulu 			mpl->m_next = mpc;
413711e25f0dSDavid C Somayajulu 			mpl = mpc;
413811e25f0dSDavid C Somayajulu 		}
413911e25f0dSDavid C Somayajulu 
414011e25f0dSDavid C Somayajulu 		ecore_chain_consume(&rxq->rx_bd_ring);
414111e25f0dSDavid C Somayajulu 		rxq->sw_rx_cons =
414211e25f0dSDavid C Somayajulu 			(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
414311e25f0dSDavid C Somayajulu 	}
414411e25f0dSDavid C Somayajulu 
414511e25f0dSDavid C Somayajulu 	if (rxq->tpa_info[agg_index].agg_state != QLNX_AGG_STATE_NONE) {
41467a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: invalid aggregation state, dropping"
41477a377fbeSDavid C Somayajulu 			" incoming packet and reusing its buffer\n",
41487a377fbeSDavid C Somayajulu 			fp->rss_id);
414911e25f0dSDavid C Somayajulu 
415011e25f0dSDavid C Somayajulu 		QLNX_INC_IQDROPS(ifp);
415111e25f0dSDavid C Somayajulu 
415211e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpf = mp;
415311e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpl = NULL;
415411e25f0dSDavid C Somayajulu 
415511e25f0dSDavid C Somayajulu 		return;
415611e25f0dSDavid C Somayajulu 	}
415711e25f0dSDavid C Somayajulu 
415811e25f0dSDavid C Somayajulu         rxq->tpa_info[agg_index].placement_offset = cqe->placement_offset;
415911e25f0dSDavid C Somayajulu 
416011e25f0dSDavid C Somayajulu         if (mpf != NULL) {
416111e25f0dSDavid C Somayajulu                 mp->m_len = ha->rx_buf_size;
416211e25f0dSDavid C Somayajulu                 mp->m_next = mpf;
416311e25f0dSDavid C Somayajulu                 rxq->tpa_info[agg_index].mpf = mp;
416411e25f0dSDavid C Somayajulu                 rxq->tpa_info[agg_index].mpl = mpl;
416511e25f0dSDavid C Somayajulu         } else {
416611e25f0dSDavid C Somayajulu                 mp->m_len = cqe->len_on_first_bd + cqe->placement_offset;
416711e25f0dSDavid C Somayajulu                 rxq->tpa_info[agg_index].mpf = mp;
416811e25f0dSDavid C Somayajulu                 rxq->tpa_info[agg_index].mpl = mp;
416911e25f0dSDavid C Somayajulu                 mp->m_next = NULL;
417011e25f0dSDavid C Somayajulu         }
417111e25f0dSDavid C Somayajulu 
417211e25f0dSDavid C Somayajulu 	mp->m_flags |= M_PKTHDR;
417311e25f0dSDavid C Somayajulu 
417411e25f0dSDavid C Somayajulu 	/* assign packet to this interface interface */
417511e25f0dSDavid C Somayajulu 	mp->m_pkthdr.rcvif = ifp;
417611e25f0dSDavid C Somayajulu 
417711e25f0dSDavid C Somayajulu 	/* assume no hardware checksum has complated */
417811e25f0dSDavid C Somayajulu 	mp->m_pkthdr.csum_flags = 0;
417911e25f0dSDavid C Somayajulu 
418011e25f0dSDavid C Somayajulu 	//mp->m_pkthdr.flowid = fp->rss_id;
418111e25f0dSDavid C Somayajulu 	mp->m_pkthdr.flowid = cqe->rss_hash;
418211e25f0dSDavid C Somayajulu 
418311e25f0dSDavid C Somayajulu 	hash_type = cqe->bitfields &
418411e25f0dSDavid C Somayajulu 			(ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE_MASK <<
418511e25f0dSDavid C Somayajulu 			ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE_SHIFT);
418611e25f0dSDavid C Somayajulu 
418711e25f0dSDavid C Somayajulu 	switch (hash_type) {
418811e25f0dSDavid C Somayajulu 	case RSS_HASH_TYPE_IPV4:
418911e25f0dSDavid C Somayajulu 		M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_IPV4);
419011e25f0dSDavid C Somayajulu 		break;
419111e25f0dSDavid C Somayajulu 
419211e25f0dSDavid C Somayajulu 	case RSS_HASH_TYPE_TCP_IPV4:
419311e25f0dSDavid C Somayajulu 		M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_TCP_IPV4);
419411e25f0dSDavid C Somayajulu 		break;
419511e25f0dSDavid C Somayajulu 
419611e25f0dSDavid C Somayajulu 	case RSS_HASH_TYPE_IPV6:
419711e25f0dSDavid C Somayajulu 		M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_IPV6);
419811e25f0dSDavid C Somayajulu 		break;
419911e25f0dSDavid C Somayajulu 
420011e25f0dSDavid C Somayajulu 	case RSS_HASH_TYPE_TCP_IPV6:
420111e25f0dSDavid C Somayajulu 		M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_TCP_IPV6);
420211e25f0dSDavid C Somayajulu 		break;
420311e25f0dSDavid C Somayajulu 
420411e25f0dSDavid C Somayajulu 	default:
420511e25f0dSDavid C Somayajulu 		M_HASHTYPE_SET(mp, M_HASHTYPE_OPAQUE);
420611e25f0dSDavid C Somayajulu 		break;
420711e25f0dSDavid C Somayajulu 	}
420811e25f0dSDavid C Somayajulu 
420911e25f0dSDavid C Somayajulu 	mp->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID |
421011e25f0dSDavid C Somayajulu 					CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
421111e25f0dSDavid C Somayajulu 
421211e25f0dSDavid C Somayajulu 	mp->m_pkthdr.csum_data = 0xFFFF;
421311e25f0dSDavid C Somayajulu 
421411e25f0dSDavid C Somayajulu 	if (CQE_HAS_VLAN(cqe->pars_flags.flags)) {
421511e25f0dSDavid C Somayajulu 		mp->m_pkthdr.ether_vtag = le16toh(cqe->vlan_tag);
421611e25f0dSDavid C Somayajulu 		mp->m_flags |= M_VLANTAG;
421711e25f0dSDavid C Somayajulu 	}
421811e25f0dSDavid C Somayajulu 
421911e25f0dSDavid C Somayajulu 	rxq->tpa_info[agg_index].agg_state = QLNX_AGG_STATE_START;
422011e25f0dSDavid C Somayajulu 
42217a377fbeSDavid C Somayajulu         QL_DPRINT7(ha, "[%d]: 5\n\tagg_state = %d\n\t mpf = %p mpl = %p\n",
42227a377fbeSDavid C Somayajulu 		fp->rss_id, rxq->tpa_info[agg_index].agg_state,
42237a377fbeSDavid C Somayajulu                 rxq->tpa_info[agg_index].mpf, rxq->tpa_info[agg_index].mpl);
422411e25f0dSDavid C Somayajulu 
422511e25f0dSDavid C Somayajulu 	return;
422611e25f0dSDavid C Somayajulu }
422711e25f0dSDavid C Somayajulu 
422811e25f0dSDavid C Somayajulu static void
qlnx_tpa_cont(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_rx_queue * rxq,struct eth_fast_path_rx_tpa_cont_cqe * cqe)422911e25f0dSDavid C Somayajulu qlnx_tpa_cont(qlnx_host_t *ha, struct qlnx_fastpath *fp,
423011e25f0dSDavid C Somayajulu 	struct qlnx_rx_queue *rxq,
423111e25f0dSDavid C Somayajulu 	struct eth_fast_path_rx_tpa_cont_cqe *cqe)
423211e25f0dSDavid C Somayajulu {
423311e25f0dSDavid C Somayajulu 	struct sw_rx_data	*sw_rx_data;
423411e25f0dSDavid C Somayajulu 	int			i;
423511e25f0dSDavid C Somayajulu 	struct mbuf		*mpf = NULL, *mpl = NULL, *mpc = NULL;
423611e25f0dSDavid C Somayajulu 	struct mbuf		*mp;
423711e25f0dSDavid C Somayajulu 	uint32_t		agg_index;
423811e25f0dSDavid C Somayajulu 
42397a377fbeSDavid C Somayajulu         QL_DPRINT7(ha, "[%d]: enter\n \
42407a377fbeSDavid C Somayajulu                 \t type = 0x%x\n \
42417a377fbeSDavid C Somayajulu                 \t tpa_agg_index = 0x%x\n \
42427a377fbeSDavid C Somayajulu                 \t len_list[0] = 0x%x\n \
42437a377fbeSDavid C Somayajulu                 \t len_list[1] = 0x%x\n \
42447a377fbeSDavid C Somayajulu                 \t len_list[2] = 0x%x\n \
42457a377fbeSDavid C Somayajulu                 \t len_list[3] = 0x%x\n \
42467a377fbeSDavid C Somayajulu                 \t len_list[4] = 0x%x\n \
42477a377fbeSDavid C Somayajulu                 \t len_list[5] = 0x%x\n",
42487a377fbeSDavid C Somayajulu                 fp->rss_id, cqe->type, cqe->tpa_agg_index,
424911e25f0dSDavid C Somayajulu                 cqe->len_list[0], cqe->len_list[1], cqe->len_list[2],
42507a377fbeSDavid C Somayajulu                 cqe->len_list[3], cqe->len_list[4], cqe->len_list[5]);
425111e25f0dSDavid C Somayajulu 
425211e25f0dSDavid C Somayajulu 	agg_index = cqe->tpa_agg_index;
425311e25f0dSDavid C Somayajulu 
425411e25f0dSDavid C Somayajulu 	if (agg_index >= ETH_TPA_MAX_AGGS_NUM) {
42557a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 0\n ", fp->rss_id);
425611e25f0dSDavid C Somayajulu 		fp->err_rx_tpa_invalid_agg_num++;
425711e25f0dSDavid C Somayajulu 		return;
425811e25f0dSDavid C Somayajulu 	}
425911e25f0dSDavid C Somayajulu 
426011e25f0dSDavid C Somayajulu 	for (i = 0; i < ETH_TPA_CQE_CONT_LEN_LIST_SIZE; i++) {
42617a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 1\n ", fp->rss_id);
426211e25f0dSDavid C Somayajulu 
426311e25f0dSDavid C Somayajulu 		if (cqe->len_list[i] == 0)
426411e25f0dSDavid C Somayajulu 			break;
426511e25f0dSDavid C Somayajulu 
426611e25f0dSDavid C Somayajulu 		if (rxq->tpa_info[agg_index].agg_state !=
426711e25f0dSDavid C Somayajulu 			QLNX_AGG_STATE_START) {
426811e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
426911e25f0dSDavid C Somayajulu 			continue;
427011e25f0dSDavid C Somayajulu 		}
427111e25f0dSDavid C Somayajulu 
427211e25f0dSDavid C Somayajulu 		sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_cons];
427311e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->rx_tag, sw_rx_data->map,
427411e25f0dSDavid C Somayajulu 			BUS_DMASYNC_POSTREAD);
427511e25f0dSDavid C Somayajulu 
427611e25f0dSDavid C Somayajulu 		mpc = sw_rx_data->data;
427711e25f0dSDavid C Somayajulu 
427811e25f0dSDavid C Somayajulu 		if (mpc == NULL) {
42797a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: mpc = NULL\n", fp->rss_id);
428011e25f0dSDavid C Somayajulu 
428111e25f0dSDavid C Somayajulu 			fp->err_rx_mp_null++;
428211e25f0dSDavid C Somayajulu 			if (mpf != NULL)
428311e25f0dSDavid C Somayajulu 				m_freem(mpf);
428411e25f0dSDavid C Somayajulu 			mpf = mpl = NULL;
428511e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].agg_state =
428611e25f0dSDavid C Somayajulu 						QLNX_AGG_STATE_ERROR;
428711e25f0dSDavid C Somayajulu 			ecore_chain_consume(&rxq->rx_bd_ring);
428811e25f0dSDavid C Somayajulu 			rxq->sw_rx_cons =
428911e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
429011e25f0dSDavid C Somayajulu 			continue;
429111e25f0dSDavid C Somayajulu 		}
429211e25f0dSDavid C Somayajulu 
429311e25f0dSDavid C Somayajulu 		if (qlnx_alloc_rx_buffer(ha, rxq) != 0) {
42947a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: New buffer allocation failed,"
42957a377fbeSDavid C Somayajulu 				" dropping incoming packet and reusing its"
42967a377fbeSDavid C Somayajulu 				" buffer\n", fp->rss_id);
429711e25f0dSDavid C Somayajulu 
429811e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
429911e25f0dSDavid C Somayajulu 
430011e25f0dSDavid C Somayajulu 			if (mpf != NULL)
430111e25f0dSDavid C Somayajulu 				m_freem(mpf);
430211e25f0dSDavid C Somayajulu 			mpf = mpl = NULL;
430311e25f0dSDavid C Somayajulu 
430411e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].agg_state =
430511e25f0dSDavid C Somayajulu 						QLNX_AGG_STATE_ERROR;
430611e25f0dSDavid C Somayajulu 
430711e25f0dSDavid C Somayajulu 			ecore_chain_consume(&rxq->rx_bd_ring);
430811e25f0dSDavid C Somayajulu 			rxq->sw_rx_cons =
430911e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
431011e25f0dSDavid C Somayajulu 
431111e25f0dSDavid C Somayajulu 			continue;
431211e25f0dSDavid C Somayajulu 		}
431311e25f0dSDavid C Somayajulu 
431411e25f0dSDavid C Somayajulu 		mpc->m_flags &= ~M_PKTHDR;
431511e25f0dSDavid C Somayajulu 		mpc->m_next = NULL;
431611e25f0dSDavid C Somayajulu 		mpc->m_len = cqe->len_list[i];
431711e25f0dSDavid C Somayajulu 
431811e25f0dSDavid C Somayajulu 		if (mpf == NULL) {
431911e25f0dSDavid C Somayajulu 			mpf = mpl = mpc;
432011e25f0dSDavid C Somayajulu 		} else {
432111e25f0dSDavid C Somayajulu 			mpl->m_len = ha->rx_buf_size;
432211e25f0dSDavid C Somayajulu 			mpl->m_next = mpc;
432311e25f0dSDavid C Somayajulu 			mpl = mpc;
432411e25f0dSDavid C Somayajulu 		}
432511e25f0dSDavid C Somayajulu 
432611e25f0dSDavid C Somayajulu 		ecore_chain_consume(&rxq->rx_bd_ring);
432711e25f0dSDavid C Somayajulu 		rxq->sw_rx_cons =
432811e25f0dSDavid C Somayajulu 			(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
432911e25f0dSDavid C Somayajulu 	}
433011e25f0dSDavid C Somayajulu 
43317a377fbeSDavid C Somayajulu         QL_DPRINT7(ha, "[%d]: 2\n" "\tmpf = %p mpl = %p\n",
43327a377fbeSDavid C Somayajulu                   fp->rss_id, mpf, mpl);
433311e25f0dSDavid C Somayajulu 
433411e25f0dSDavid C Somayajulu 	if (mpf != NULL) {
433511e25f0dSDavid C Somayajulu 		mp = rxq->tpa_info[agg_index].mpl;
433611e25f0dSDavid C Somayajulu 		mp->m_len = ha->rx_buf_size;
433711e25f0dSDavid C Somayajulu 		mp->m_next = mpf;
433811e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpl = mpl;
433911e25f0dSDavid C Somayajulu 	}
434011e25f0dSDavid C Somayajulu 
434111e25f0dSDavid C Somayajulu 	return;
434211e25f0dSDavid C Somayajulu }
434311e25f0dSDavid C Somayajulu 
434411e25f0dSDavid C Somayajulu static int
qlnx_tpa_end(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_rx_queue * rxq,struct eth_fast_path_rx_tpa_end_cqe * cqe)434511e25f0dSDavid C Somayajulu qlnx_tpa_end(qlnx_host_t *ha, struct qlnx_fastpath *fp,
434611e25f0dSDavid C Somayajulu 	struct qlnx_rx_queue *rxq,
434711e25f0dSDavid C Somayajulu 	struct eth_fast_path_rx_tpa_end_cqe *cqe)
434811e25f0dSDavid C Somayajulu {
434911e25f0dSDavid C Somayajulu 	struct sw_rx_data	*sw_rx_data;
435011e25f0dSDavid C Somayajulu 	int			i;
435111e25f0dSDavid C Somayajulu 	struct mbuf		*mpf = NULL, *mpl = NULL, *mpc = NULL;
435211e25f0dSDavid C Somayajulu 	struct mbuf		*mp;
435311e25f0dSDavid C Somayajulu 	uint32_t		agg_index;
435411e25f0dSDavid C Somayajulu 	uint32_t		len = 0;
4355727bfe38SJustin Hibbits         if_t ifp = ha->ifp;
435611e25f0dSDavid C Somayajulu 
43577a377fbeSDavid C Somayajulu         QL_DPRINT7(ha, "[%d]: enter\n \
43587a377fbeSDavid C Somayajulu                 \t type = 0x%x\n \
43597a377fbeSDavid C Somayajulu                 \t tpa_agg_index = 0x%x\n \
43607a377fbeSDavid C Somayajulu                 \t total_packet_len = 0x%x\n \
43617a377fbeSDavid C Somayajulu                 \t num_of_bds = 0x%x\n \
43627a377fbeSDavid C Somayajulu                 \t end_reason = 0x%x\n \
43637a377fbeSDavid C Somayajulu                 \t num_of_coalesced_segs = 0x%x\n \
43647a377fbeSDavid C Somayajulu                 \t ts_delta = 0x%x\n \
43657a377fbeSDavid C Somayajulu                 \t len_list[0] = 0x%x\n \
43667a377fbeSDavid C Somayajulu                 \t len_list[1] = 0x%x\n \
43677a377fbeSDavid C Somayajulu                 \t len_list[2] = 0x%x\n \
43687a377fbeSDavid C Somayajulu                 \t len_list[3] = 0x%x\n",
43697a377fbeSDavid C Somayajulu                  fp->rss_id, cqe->type, cqe->tpa_agg_index,
437011e25f0dSDavid C Somayajulu                 cqe->total_packet_len, cqe->num_of_bds,
437111e25f0dSDavid C Somayajulu                 cqe->end_reason, cqe->num_of_coalesced_segs, cqe->ts_delta,
437211e25f0dSDavid C Somayajulu                 cqe->len_list[0], cqe->len_list[1], cqe->len_list[2],
43737a377fbeSDavid C Somayajulu                 cqe->len_list[3]);
437411e25f0dSDavid C Somayajulu 
437511e25f0dSDavid C Somayajulu 	agg_index = cqe->tpa_agg_index;
437611e25f0dSDavid C Somayajulu 
437711e25f0dSDavid C Somayajulu 	if (agg_index >= ETH_TPA_MAX_AGGS_NUM) {
43787a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 0\n ", fp->rss_id);
437911e25f0dSDavid C Somayajulu 
438011e25f0dSDavid C Somayajulu 		fp->err_rx_tpa_invalid_agg_num++;
438111e25f0dSDavid C Somayajulu 		return (0);
438211e25f0dSDavid C Somayajulu 	}
438311e25f0dSDavid C Somayajulu 
438411e25f0dSDavid C Somayajulu 	for (i = 0; i < ETH_TPA_CQE_END_LEN_LIST_SIZE; i++) {
43857a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 1\n ", fp->rss_id);
438611e25f0dSDavid C Somayajulu 
438711e25f0dSDavid C Somayajulu 		if (cqe->len_list[i] == 0)
438811e25f0dSDavid C Somayajulu 			break;
438911e25f0dSDavid C Somayajulu 
439011e25f0dSDavid C Somayajulu 		if (rxq->tpa_info[agg_index].agg_state !=
439111e25f0dSDavid C Somayajulu 			QLNX_AGG_STATE_START) {
43927a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: 2\n ", fp->rss_id);
439311e25f0dSDavid C Somayajulu 
439411e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
439511e25f0dSDavid C Somayajulu 			continue;
439611e25f0dSDavid C Somayajulu 		}
439711e25f0dSDavid C Somayajulu 
439811e25f0dSDavid C Somayajulu 		sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_cons];
439911e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->rx_tag, sw_rx_data->map,
440011e25f0dSDavid C Somayajulu 			BUS_DMASYNC_POSTREAD);
440111e25f0dSDavid C Somayajulu 
440211e25f0dSDavid C Somayajulu 		mpc = sw_rx_data->data;
440311e25f0dSDavid C Somayajulu 
440411e25f0dSDavid C Somayajulu 		if (mpc == NULL) {
44057a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: mpc = NULL\n", fp->rss_id);
440611e25f0dSDavid C Somayajulu 
440711e25f0dSDavid C Somayajulu 			fp->err_rx_mp_null++;
440811e25f0dSDavid C Somayajulu 			if (mpf != NULL)
440911e25f0dSDavid C Somayajulu 				m_freem(mpf);
441011e25f0dSDavid C Somayajulu 			mpf = mpl = NULL;
441111e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].agg_state =
441211e25f0dSDavid C Somayajulu 						QLNX_AGG_STATE_ERROR;
441311e25f0dSDavid C Somayajulu 			ecore_chain_consume(&rxq->rx_bd_ring);
441411e25f0dSDavid C Somayajulu 			rxq->sw_rx_cons =
441511e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
441611e25f0dSDavid C Somayajulu 			continue;
441711e25f0dSDavid C Somayajulu 		}
441811e25f0dSDavid C Somayajulu 
441911e25f0dSDavid C Somayajulu 		if (qlnx_alloc_rx_buffer(ha, rxq) != 0) {
44207a377fbeSDavid C Somayajulu 			QL_DPRINT7(ha, "[%d]: New buffer allocation failed,"
44217a377fbeSDavid C Somayajulu 				" dropping incoming packet and reusing its"
44227a377fbeSDavid C Somayajulu 				" buffer\n", fp->rss_id);
442311e25f0dSDavid C Somayajulu 
442411e25f0dSDavid C Somayajulu 			qlnx_reuse_rx_data(rxq);
442511e25f0dSDavid C Somayajulu 
442611e25f0dSDavid C Somayajulu 			if (mpf != NULL)
442711e25f0dSDavid C Somayajulu 				m_freem(mpf);
442811e25f0dSDavid C Somayajulu 			mpf = mpl = NULL;
442911e25f0dSDavid C Somayajulu 
443011e25f0dSDavid C Somayajulu 			rxq->tpa_info[agg_index].agg_state =
443111e25f0dSDavid C Somayajulu 						QLNX_AGG_STATE_ERROR;
443211e25f0dSDavid C Somayajulu 
443311e25f0dSDavid C Somayajulu 			ecore_chain_consume(&rxq->rx_bd_ring);
443411e25f0dSDavid C Somayajulu 			rxq->sw_rx_cons =
443511e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
443611e25f0dSDavid C Somayajulu 
443711e25f0dSDavid C Somayajulu 			continue;
443811e25f0dSDavid C Somayajulu 		}
443911e25f0dSDavid C Somayajulu 
444011e25f0dSDavid C Somayajulu 		mpc->m_flags &= ~M_PKTHDR;
444111e25f0dSDavid C Somayajulu 		mpc->m_next = NULL;
444211e25f0dSDavid C Somayajulu 		mpc->m_len = cqe->len_list[i];
444311e25f0dSDavid C Somayajulu 
444411e25f0dSDavid C Somayajulu 		if (mpf == NULL) {
444511e25f0dSDavid C Somayajulu 			mpf = mpl = mpc;
444611e25f0dSDavid C Somayajulu 		} else {
444711e25f0dSDavid C Somayajulu 			mpl->m_len = ha->rx_buf_size;
444811e25f0dSDavid C Somayajulu 			mpl->m_next = mpc;
444911e25f0dSDavid C Somayajulu 			mpl = mpc;
445011e25f0dSDavid C Somayajulu 		}
445111e25f0dSDavid C Somayajulu 
445211e25f0dSDavid C Somayajulu 		ecore_chain_consume(&rxq->rx_bd_ring);
445311e25f0dSDavid C Somayajulu 		rxq->sw_rx_cons =
445411e25f0dSDavid C Somayajulu 			(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
445511e25f0dSDavid C Somayajulu 	}
445611e25f0dSDavid C Somayajulu 
44577a377fbeSDavid C Somayajulu 	QL_DPRINT7(ha, "[%d]: 5\n ", fp->rss_id);
445811e25f0dSDavid C Somayajulu 
445911e25f0dSDavid C Somayajulu 	if (mpf != NULL) {
44607a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 6\n ", fp->rss_id);
446111e25f0dSDavid C Somayajulu 
446211e25f0dSDavid C Somayajulu 		mp = rxq->tpa_info[agg_index].mpl;
446311e25f0dSDavid C Somayajulu 		mp->m_len = ha->rx_buf_size;
446411e25f0dSDavid C Somayajulu 		mp->m_next = mpf;
446511e25f0dSDavid C Somayajulu 	}
446611e25f0dSDavid C Somayajulu 
446711e25f0dSDavid C Somayajulu 	if (rxq->tpa_info[agg_index].agg_state != QLNX_AGG_STATE_START) {
44687a377fbeSDavid C Somayajulu 		QL_DPRINT7(ha, "[%d]: 7\n ", fp->rss_id);
446911e25f0dSDavid C Somayajulu 
447011e25f0dSDavid C Somayajulu 		if (rxq->tpa_info[agg_index].mpf != NULL)
447111e25f0dSDavid C Somayajulu 			m_freem(rxq->tpa_info[agg_index].mpf);
447211e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpf = NULL;
447311e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].mpl = NULL;
447411e25f0dSDavid C Somayajulu 		rxq->tpa_info[agg_index].agg_state = QLNX_AGG_STATE_NONE;
447511e25f0dSDavid C Somayajulu 		return (0);
447611e25f0dSDavid C Somayajulu 	}
447711e25f0dSDavid C Somayajulu 
447811e25f0dSDavid C Somayajulu 	mp = rxq->tpa_info[agg_index].mpf;
447911e25f0dSDavid C Somayajulu 	m_adj(mp, rxq->tpa_info[agg_index].placement_offset);
448011e25f0dSDavid C Somayajulu 	mp->m_pkthdr.len = cqe->total_packet_len;
448111e25f0dSDavid C Somayajulu 
448211e25f0dSDavid C Somayajulu 	if (mp->m_next  == NULL)
448311e25f0dSDavid C Somayajulu 		mp->m_len = mp->m_pkthdr.len;
448411e25f0dSDavid C Somayajulu 	else {
448511e25f0dSDavid C Somayajulu 		/* compute the total packet length */
448611e25f0dSDavid C Somayajulu 		mpf = mp;
448711e25f0dSDavid C Somayajulu 		while (mpf != NULL) {
448811e25f0dSDavid C Somayajulu 			len += mpf->m_len;
448911e25f0dSDavid C Somayajulu 			mpf = mpf->m_next;
449011e25f0dSDavid C Somayajulu 		}
449111e25f0dSDavid C Somayajulu 
449211e25f0dSDavid C Somayajulu 		if (cqe->total_packet_len > len) {
449311e25f0dSDavid C Somayajulu 			mpl = rxq->tpa_info[agg_index].mpl;
449411e25f0dSDavid C Somayajulu 			mpl->m_len += (cqe->total_packet_len - len);
449511e25f0dSDavid C Somayajulu 		}
449611e25f0dSDavid C Somayajulu 	}
449711e25f0dSDavid C Somayajulu 
449811e25f0dSDavid C Somayajulu 	QLNX_INC_IPACKETS(ifp);
449911e25f0dSDavid C Somayajulu 	QLNX_INC_IBYTES(ifp, (cqe->total_packet_len));
450011e25f0dSDavid C Somayajulu 
4501217ec208SDavid C Somayajulu         QL_DPRINT7(ha, "[%d]: 8 csum_data = 0x%x csum_flags = 0x%" PRIu64 "\n \
45027a377fbeSDavid C Somayajulu 		m_len = 0x%x m_pkthdr_len = 0x%x\n",
45037a377fbeSDavid C Somayajulu                 fp->rss_id, mp->m_pkthdr.csum_data,
4504217ec208SDavid C Somayajulu                 (uint64_t)mp->m_pkthdr.csum_flags, mp->m_len, mp->m_pkthdr.len);
450511e25f0dSDavid C Somayajulu 
4506727bfe38SJustin Hibbits 	if_input(ifp, mp);
450711e25f0dSDavid C Somayajulu 
450811e25f0dSDavid C Somayajulu 	rxq->tpa_info[agg_index].mpf = NULL;
450911e25f0dSDavid C Somayajulu 	rxq->tpa_info[agg_index].mpl = NULL;
451011e25f0dSDavid C Somayajulu 	rxq->tpa_info[agg_index].agg_state = QLNX_AGG_STATE_NONE;
451111e25f0dSDavid C Somayajulu 
451211e25f0dSDavid C Somayajulu 	return (cqe->num_of_coalesced_segs);
451311e25f0dSDavid C Somayajulu }
451411e25f0dSDavid C Somayajulu 
451511e25f0dSDavid C Somayajulu static int
qlnx_rx_int(qlnx_host_t * ha,struct qlnx_fastpath * fp,int budget,int lro_enable)451611e25f0dSDavid C Somayajulu qlnx_rx_int(qlnx_host_t *ha, struct qlnx_fastpath *fp, int budget,
451711e25f0dSDavid C Somayajulu 	int lro_enable)
451811e25f0dSDavid C Somayajulu {
451911e25f0dSDavid C Somayajulu         uint16_t		hw_comp_cons, sw_comp_cons;
452011e25f0dSDavid C Somayajulu         int			rx_pkt = 0;
452111e25f0dSDavid C Somayajulu         struct qlnx_rx_queue	*rxq = fp->rxq;
4522727bfe38SJustin Hibbits         if_t ifp = ha->ifp;
452311e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev = &ha->cdev;
452411e25f0dSDavid C Somayajulu 	struct ecore_hwfn       *p_hwfn;
452511e25f0dSDavid C Somayajulu 
452611e25f0dSDavid C Somayajulu #ifdef QLNX_SOFT_LRO
452711e25f0dSDavid C Somayajulu 	struct lro_ctrl		*lro;
452811e25f0dSDavid C Somayajulu 
452911e25f0dSDavid C Somayajulu 	lro = &rxq->lro;
453011e25f0dSDavid C Somayajulu #endif /* #ifdef QLNX_SOFT_LRO */
453111e25f0dSDavid C Somayajulu 
453211e25f0dSDavid C Somayajulu         hw_comp_cons = le16toh(*rxq->hw_cons_ptr);
453311e25f0dSDavid C Somayajulu         sw_comp_cons = ecore_chain_get_cons_idx(&rxq->rx_comp_ring);
453411e25f0dSDavid C Somayajulu 
453511e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[(fp->rss_id % cdev->num_hwfns)];
453611e25f0dSDavid C Somayajulu 
453711e25f0dSDavid C Somayajulu         /* Memory barrier to prevent the CPU from doing speculative reads of CQE
453811e25f0dSDavid C Somayajulu          * / BD in the while-loop before reading hw_comp_cons. If the CQE is
453911e25f0dSDavid C Somayajulu          * read before it is written by FW, then FW writes CQE and SB, and then
454011e25f0dSDavid C Somayajulu          * the CPU reads the hw_comp_cons, it will use an old CQE.
454111e25f0dSDavid C Somayajulu          */
454211e25f0dSDavid C Somayajulu 
454311e25f0dSDavid C Somayajulu         /* Loop to complete all indicated BDs */
454411e25f0dSDavid C Somayajulu         while (sw_comp_cons != hw_comp_cons) {
454511e25f0dSDavid C Somayajulu                 union eth_rx_cqe		*cqe;
454611e25f0dSDavid C Somayajulu                 struct eth_fast_path_rx_reg_cqe	*fp_cqe;
454711e25f0dSDavid C Somayajulu                 struct sw_rx_data		*sw_rx_data;
454811e25f0dSDavid C Somayajulu 		register struct mbuf		*mp;
454911e25f0dSDavid C Somayajulu                 enum eth_rx_cqe_type		cqe_type;
455011e25f0dSDavid C Somayajulu                 uint16_t			len, pad, len_on_first_bd;
455111e25f0dSDavid C Somayajulu                 uint8_t				*data;
455211e25f0dSDavid C Somayajulu 		uint8_t				hash_type;
455311e25f0dSDavid C Somayajulu 
455411e25f0dSDavid C Somayajulu                 /* Get the CQE from the completion ring */
455511e25f0dSDavid C Somayajulu                 cqe = (union eth_rx_cqe *)
455611e25f0dSDavid C Somayajulu                         ecore_chain_consume(&rxq->rx_comp_ring);
455711e25f0dSDavid C Somayajulu                 cqe_type = cqe->fast_path_regular.type;
455811e25f0dSDavid C Somayajulu 
455911e25f0dSDavid C Somayajulu                 if (cqe_type == ETH_RX_CQE_TYPE_SLOW_PATH) {
45607a377fbeSDavid C Somayajulu                         QL_DPRINT3(ha, "Got a slowath CQE\n");
456111e25f0dSDavid C Somayajulu 
456211e25f0dSDavid C Somayajulu                         ecore_eth_cqe_completion(p_hwfn,
456311e25f0dSDavid C Somayajulu                                         (struct eth_slow_path_rx_cqe *)cqe);
456411e25f0dSDavid C Somayajulu                         goto next_cqe;
456511e25f0dSDavid C Somayajulu                 }
456611e25f0dSDavid C Somayajulu 
456711e25f0dSDavid C Somayajulu 		if (cqe_type != ETH_RX_CQE_TYPE_REGULAR) {
456811e25f0dSDavid C Somayajulu 			switch (cqe_type) {
456911e25f0dSDavid C Somayajulu 			case ETH_RX_CQE_TYPE_TPA_START:
457011e25f0dSDavid C Somayajulu 				qlnx_tpa_start(ha, fp, rxq,
457111e25f0dSDavid C Somayajulu 					&cqe->fast_path_tpa_start);
457211e25f0dSDavid C Somayajulu 				fp->tpa_start++;
457311e25f0dSDavid C Somayajulu 				break;
457411e25f0dSDavid C Somayajulu 
457511e25f0dSDavid C Somayajulu 			case ETH_RX_CQE_TYPE_TPA_CONT:
457611e25f0dSDavid C Somayajulu 				qlnx_tpa_cont(ha, fp, rxq,
457711e25f0dSDavid C Somayajulu 					&cqe->fast_path_tpa_cont);
457811e25f0dSDavid C Somayajulu 				fp->tpa_cont++;
457911e25f0dSDavid C Somayajulu 				break;
458011e25f0dSDavid C Somayajulu 
458111e25f0dSDavid C Somayajulu 			case ETH_RX_CQE_TYPE_TPA_END:
458211e25f0dSDavid C Somayajulu 				rx_pkt += qlnx_tpa_end(ha, fp, rxq,
458311e25f0dSDavid C Somayajulu 						&cqe->fast_path_tpa_end);
458411e25f0dSDavid C Somayajulu 				fp->tpa_end++;
458511e25f0dSDavid C Somayajulu 				break;
458611e25f0dSDavid C Somayajulu 
458711e25f0dSDavid C Somayajulu 			default:
458811e25f0dSDavid C Somayajulu 				break;
458911e25f0dSDavid C Somayajulu 			}
459011e25f0dSDavid C Somayajulu 
459111e25f0dSDavid C Somayajulu                         goto next_cqe;
459211e25f0dSDavid C Somayajulu 		}
459311e25f0dSDavid C Somayajulu 
459411e25f0dSDavid C Somayajulu                 /* Get the data from the SW ring */
459511e25f0dSDavid C Somayajulu                 sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_cons];
459611e25f0dSDavid C Somayajulu                 mp = sw_rx_data->data;
459711e25f0dSDavid C Somayajulu 
459811e25f0dSDavid C Somayajulu 		if (mp == NULL) {
45997a377fbeSDavid C Somayajulu                 	QL_DPRINT1(ha, "mp = NULL\n");
460011e25f0dSDavid C Somayajulu 			fp->err_rx_mp_null++;
460111e25f0dSDavid C Somayajulu         		rxq->sw_rx_cons  =
460211e25f0dSDavid C Somayajulu 				(rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
460311e25f0dSDavid C Somayajulu 			goto next_cqe;
460411e25f0dSDavid C Somayajulu 		}
460511e25f0dSDavid C Somayajulu 		bus_dmamap_sync(ha->rx_tag, sw_rx_data->map,
460611e25f0dSDavid C Somayajulu 			BUS_DMASYNC_POSTREAD);
460711e25f0dSDavid C Somayajulu 
460811e25f0dSDavid C Somayajulu                 /* non GRO */
460911e25f0dSDavid C Somayajulu                 fp_cqe = &cqe->fast_path_regular;/* MK CR TPA check assembly */
461011e25f0dSDavid C Somayajulu                 len =  le16toh(fp_cqe->pkt_len);
461111e25f0dSDavid C Somayajulu                 pad = fp_cqe->placement_offset;
4612217ec208SDavid C Somayajulu #if 0
46137a377fbeSDavid C Somayajulu 		QL_DPRINT3(ha, "CQE type = %x, flags = %x, vlan = %x,"
461411e25f0dSDavid C Somayajulu 			" len %u, parsing flags = %d pad  = %d\n",
461511e25f0dSDavid C Somayajulu 			cqe_type, fp_cqe->bitfields,
461611e25f0dSDavid C Somayajulu 			le16toh(fp_cqe->vlan_tag),
46177a377fbeSDavid C Somayajulu 			len, le16toh(fp_cqe->pars_flags.flags), pad);
4618217ec208SDavid C Somayajulu #endif
461911e25f0dSDavid C Somayajulu 		data = mtod(mp, uint8_t *);
462011e25f0dSDavid C Somayajulu 		data = data + pad;
462111e25f0dSDavid C Somayajulu 
462211e25f0dSDavid C Somayajulu 		if (0)
462311e25f0dSDavid C Somayajulu 			qlnx_dump_buf8(ha, __func__, data, len);
462411e25f0dSDavid C Somayajulu 
462511e25f0dSDavid C Somayajulu                 /* For every Rx BD consumed, we allocate a new BD so the BD ring
462611e25f0dSDavid C Somayajulu                  * is always with a fixed size. If allocation fails, we take the
462711e25f0dSDavid C Somayajulu                  * consumed BD and return it to the ring in the PROD position.
462811e25f0dSDavid C Somayajulu                  * The packet that was received on that BD will be dropped (and
462911e25f0dSDavid C Somayajulu                  * not passed to the upper stack).
463011e25f0dSDavid C Somayajulu                  */
463111e25f0dSDavid C Somayajulu 		/* If this is an error packet then drop it */
463211e25f0dSDavid C Somayajulu 		if ((le16toh(cqe->fast_path_regular.pars_flags.flags)) &
463311e25f0dSDavid C Somayajulu 			CQE_FLAGS_ERR) {
46347a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "CQE in CONS = %u has error, flags = %x,"
463511e25f0dSDavid C Somayajulu 				" dropping incoming packet\n", sw_comp_cons,
46367a377fbeSDavid C Somayajulu 			le16toh(cqe->fast_path_regular.pars_flags.flags));
463711e25f0dSDavid C Somayajulu 			fp->err_rx_hw_errors++;
463811e25f0dSDavid C Somayajulu 
463911e25f0dSDavid C Somayajulu                         qlnx_reuse_rx_data(rxq);
464011e25f0dSDavid C Somayajulu 
464111e25f0dSDavid C Somayajulu 			QLNX_INC_IERRORS(ifp);
464211e25f0dSDavid C Somayajulu 
464311e25f0dSDavid C Somayajulu 			goto next_cqe;
464411e25f0dSDavid C Somayajulu 		}
464511e25f0dSDavid C Somayajulu 
464611e25f0dSDavid C Somayajulu                 if (qlnx_alloc_rx_buffer(ha, rxq) != 0) {
46477a377fbeSDavid C Somayajulu                         QL_DPRINT1(ha, "New buffer allocation failed, dropping"
46487a377fbeSDavid C Somayajulu 				" incoming packet and reusing its buffer\n");
464911e25f0dSDavid C Somayajulu                         qlnx_reuse_rx_data(rxq);
465011e25f0dSDavid C Somayajulu 
465111e25f0dSDavid C Somayajulu                         fp->err_rx_alloc_errors++;
465211e25f0dSDavid C Somayajulu 
465311e25f0dSDavid C Somayajulu 			QLNX_INC_IQDROPS(ifp);
465411e25f0dSDavid C Somayajulu 
465511e25f0dSDavid C Somayajulu                         goto next_cqe;
465611e25f0dSDavid C Somayajulu                 }
465711e25f0dSDavid C Somayajulu 
465811e25f0dSDavid C Somayajulu                 ecore_chain_consume(&rxq->rx_bd_ring);
465911e25f0dSDavid C Somayajulu 
466011e25f0dSDavid C Somayajulu 		len_on_first_bd = fp_cqe->len_on_first_bd;
466111e25f0dSDavid C Somayajulu 		m_adj(mp, pad);
466211e25f0dSDavid C Somayajulu 		mp->m_pkthdr.len = len;
466311e25f0dSDavid C Somayajulu 
466411e25f0dSDavid C Somayajulu 		if ((len > 60 ) && (len > len_on_first_bd)) {
466511e25f0dSDavid C Somayajulu 			mp->m_len = len_on_first_bd;
466611e25f0dSDavid C Somayajulu 
466711e25f0dSDavid C Somayajulu 			if (qlnx_rx_jumbo_chain(ha, fp, mp,
466811e25f0dSDavid C Somayajulu 				(len - len_on_first_bd)) != 0) {
466911e25f0dSDavid C Somayajulu 				m_freem(mp);
467011e25f0dSDavid C Somayajulu 
467111e25f0dSDavid C Somayajulu 				QLNX_INC_IQDROPS(ifp);
467211e25f0dSDavid C Somayajulu 
467311e25f0dSDavid C Somayajulu                         	goto next_cqe;
467411e25f0dSDavid C Somayajulu 			}
467511e25f0dSDavid C Somayajulu 
467611e25f0dSDavid C Somayajulu 		} else if (len_on_first_bd < len) {
467711e25f0dSDavid C Somayajulu 			fp->err_rx_jumbo_chain_pkts++;
467811e25f0dSDavid C Somayajulu 		} else {
467911e25f0dSDavid C Somayajulu 			mp->m_len = len;
468011e25f0dSDavid C Somayajulu 		}
468111e25f0dSDavid C Somayajulu 
468211e25f0dSDavid C Somayajulu 		mp->m_flags |= M_PKTHDR;
468311e25f0dSDavid C Somayajulu 
468411e25f0dSDavid C Somayajulu 		/* assign packet to this interface interface */
468511e25f0dSDavid C Somayajulu 		mp->m_pkthdr.rcvif = ifp;
468611e25f0dSDavid C Somayajulu 
468711e25f0dSDavid C Somayajulu 		/* assume no hardware checksum has complated */
468811e25f0dSDavid C Somayajulu 		mp->m_pkthdr.csum_flags = 0;
468911e25f0dSDavid C Somayajulu 
469011e25f0dSDavid C Somayajulu 		mp->m_pkthdr.flowid = fp_cqe->rss_hash;
469111e25f0dSDavid C Somayajulu 
469211e25f0dSDavid C Somayajulu 		hash_type = fp_cqe->bitfields &
469311e25f0dSDavid C Somayajulu 				(ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE_MASK <<
469411e25f0dSDavid C Somayajulu 				ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE_SHIFT);
469511e25f0dSDavid C Somayajulu 
469611e25f0dSDavid C Somayajulu 		switch (hash_type) {
469711e25f0dSDavid C Somayajulu 		case RSS_HASH_TYPE_IPV4:
469811e25f0dSDavid C Somayajulu 			M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_IPV4);
469911e25f0dSDavid C Somayajulu 			break;
470011e25f0dSDavid C Somayajulu 
470111e25f0dSDavid C Somayajulu 		case RSS_HASH_TYPE_TCP_IPV4:
470211e25f0dSDavid C Somayajulu 			M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_TCP_IPV4);
470311e25f0dSDavid C Somayajulu 			break;
470411e25f0dSDavid C Somayajulu 
470511e25f0dSDavid C Somayajulu 		case RSS_HASH_TYPE_IPV6:
470611e25f0dSDavid C Somayajulu 			M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_IPV6);
470711e25f0dSDavid C Somayajulu 			break;
470811e25f0dSDavid C Somayajulu 
470911e25f0dSDavid C Somayajulu 		case RSS_HASH_TYPE_TCP_IPV6:
471011e25f0dSDavid C Somayajulu 			M_HASHTYPE_SET(mp, M_HASHTYPE_RSS_TCP_IPV6);
471111e25f0dSDavid C Somayajulu 			break;
471211e25f0dSDavid C Somayajulu 
471311e25f0dSDavid C Somayajulu 		default:
471411e25f0dSDavid C Somayajulu 			M_HASHTYPE_SET(mp, M_HASHTYPE_OPAQUE);
471511e25f0dSDavid C Somayajulu 			break;
471611e25f0dSDavid C Somayajulu 		}
471711e25f0dSDavid C Somayajulu 
471811e25f0dSDavid C Somayajulu 		if (CQE_L3_PACKET(fp_cqe->pars_flags.flags)) {
471911e25f0dSDavid C Somayajulu 			mp->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
472011e25f0dSDavid C Somayajulu 		}
472111e25f0dSDavid C Somayajulu 
472211e25f0dSDavid C Somayajulu 		if (!(CQE_IP_HDR_ERR(fp_cqe->pars_flags.flags))) {
472311e25f0dSDavid C Somayajulu 			mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
472411e25f0dSDavid C Somayajulu 		}
472511e25f0dSDavid C Somayajulu 
472611e25f0dSDavid C Somayajulu 		if (CQE_L4_HAS_CSUM(fp_cqe->pars_flags.flags)) {
472711e25f0dSDavid C Somayajulu 			mp->m_pkthdr.csum_data = 0xFFFF;
472811e25f0dSDavid C Somayajulu 			mp->m_pkthdr.csum_flags |=
472911e25f0dSDavid C Somayajulu 				(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
473011e25f0dSDavid C Somayajulu 		}
473111e25f0dSDavid C Somayajulu 
473211e25f0dSDavid C Somayajulu 		if (CQE_HAS_VLAN(fp_cqe->pars_flags.flags)) {
473311e25f0dSDavid C Somayajulu 			mp->m_pkthdr.ether_vtag = le16toh(fp_cqe->vlan_tag);
473411e25f0dSDavid C Somayajulu 			mp->m_flags |= M_VLANTAG;
473511e25f0dSDavid C Somayajulu 		}
473611e25f0dSDavid C Somayajulu 
473711e25f0dSDavid C Somayajulu 		QLNX_INC_IPACKETS(ifp);
473811e25f0dSDavid C Somayajulu 		QLNX_INC_IBYTES(ifp, len);
473911e25f0dSDavid C Somayajulu 
474011e25f0dSDavid C Somayajulu #ifdef QLNX_SOFT_LRO
4741bbe35708SElliott Mitchell 		if (lro_enable)
474211e25f0dSDavid C Somayajulu 			tcp_lro_queue_mbuf(lro, mp);
4743bbe35708SElliott Mitchell 		else
4744727bfe38SJustin Hibbits 			if_input(ifp, mp);
474511e25f0dSDavid C Somayajulu #else
474611e25f0dSDavid C Somayajulu 
4747727bfe38SJustin Hibbits 		if_input(ifp, mp);
474811e25f0dSDavid C Somayajulu 
474911e25f0dSDavid C Somayajulu #endif /* #ifdef QLNX_SOFT_LRO */
475011e25f0dSDavid C Somayajulu 
475111e25f0dSDavid C Somayajulu                 rx_pkt++;
475211e25f0dSDavid C Somayajulu 
475311e25f0dSDavid C Somayajulu         	rxq->sw_rx_cons  = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
475411e25f0dSDavid C Somayajulu 
475511e25f0dSDavid C Somayajulu next_cqe:	/* don't consume bd rx buffer */
475611e25f0dSDavid C Somayajulu                 ecore_chain_recycle_consumed(&rxq->rx_comp_ring);
475711e25f0dSDavid C Somayajulu                 sw_comp_cons = ecore_chain_get_cons_idx(&rxq->rx_comp_ring);
475811e25f0dSDavid C Somayajulu 
475911e25f0dSDavid C Somayajulu 		/* CR TPA - revisit how to handle budget in TPA perhaps
476011e25f0dSDavid C Somayajulu 		   increase on "end" */
476111e25f0dSDavid C Somayajulu                 if (rx_pkt == budget)
476211e25f0dSDavid C Somayajulu                         break;
476311e25f0dSDavid C Somayajulu         } /* repeat while sw_comp_cons != hw_comp_cons... */
476411e25f0dSDavid C Somayajulu 
476511e25f0dSDavid C Somayajulu         /* Update producers */
476611e25f0dSDavid C Somayajulu         qlnx_update_rx_prod(p_hwfn, rxq);
476711e25f0dSDavid C Somayajulu 
476811e25f0dSDavid C Somayajulu         return rx_pkt;
476911e25f0dSDavid C Somayajulu }
477011e25f0dSDavid C Somayajulu 
477111e25f0dSDavid C Somayajulu /*
477211e25f0dSDavid C Somayajulu  * fast path interrupt
477311e25f0dSDavid C Somayajulu  */
477411e25f0dSDavid C Somayajulu 
477511e25f0dSDavid C Somayajulu static void
qlnx_fp_isr(void * arg)477611e25f0dSDavid C Somayajulu qlnx_fp_isr(void *arg)
477711e25f0dSDavid C Somayajulu {
477811e25f0dSDavid C Somayajulu         qlnx_ivec_t		*ivec = arg;
477911e25f0dSDavid C Somayajulu         qlnx_host_t		*ha;
478011e25f0dSDavid C Somayajulu         struct qlnx_fastpath	*fp = NULL;
478177388ed2SDavid C Somayajulu         int			idx;
478211e25f0dSDavid C Somayajulu 
478311e25f0dSDavid C Somayajulu         ha = ivec->ha;
478411e25f0dSDavid C Somayajulu 
478511e25f0dSDavid C Somayajulu         if (ha->state != QLNX_STATE_OPEN) {
478611e25f0dSDavid C Somayajulu                 return;
478711e25f0dSDavid C Somayajulu         }
478811e25f0dSDavid C Somayajulu 
478911e25f0dSDavid C Somayajulu         idx = ivec->rss_idx;
479011e25f0dSDavid C Somayajulu 
479111e25f0dSDavid C Somayajulu         if ((idx = ivec->rss_idx) >= ha->num_rss) {
47927a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "illegal interrupt[%d]\n", idx);
479311e25f0dSDavid C Somayajulu                 ha->err_illegal_intr++;
479411e25f0dSDavid C Somayajulu                 return;
479511e25f0dSDavid C Somayajulu         }
479611e25f0dSDavid C Somayajulu         fp = &ha->fp_array[idx];
479711e25f0dSDavid C Somayajulu 
479811e25f0dSDavid C Somayajulu         if (fp == NULL) {
479911e25f0dSDavid C Somayajulu                 ha->err_fp_null++;
480011e25f0dSDavid C Somayajulu         } else {
48013415775dSJohn Baldwin 		int			rx_int = 0;
48023415775dSJohn Baldwin #ifdef QLNX_SOFT_LRO
48033415775dSJohn Baldwin 		int			total_rx_count = 0;
48043415775dSJohn Baldwin #endif
4805b284b46dSDavid C Somayajulu 		int 			lro_enable, tc;
480645f13123SDavid C Somayajulu 		struct qlnx_tx_queue	*txq;
480745f13123SDavid C Somayajulu 		uint16_t		elem_left;
4808b284b46dSDavid C Somayajulu 
4809727bfe38SJustin Hibbits 		lro_enable = if_getcapenable(ha->ifp) & IFCAP_LRO;
4810b284b46dSDavid C Somayajulu 
4811b284b46dSDavid C Somayajulu                 ecore_sb_ack(fp->sb_info, IGU_INT_DISABLE, 0);
4812b284b46dSDavid C Somayajulu 
4813b284b46dSDavid C Somayajulu                 do {
4814b284b46dSDavid C Somayajulu                         for (tc = 0; tc < ha->num_tc; tc++) {
481545f13123SDavid C Somayajulu 				txq = fp->txq[tc];
481645f13123SDavid C Somayajulu 
481745f13123SDavid C Somayajulu 				if((int)(elem_left =
481845f13123SDavid C Somayajulu 					ecore_chain_get_elem_left(&txq->tx_pbl)) <
481945f13123SDavid C Somayajulu 						QLNX_TX_ELEM_THRESH)  {
4820b284b46dSDavid C Somayajulu                                 	if (mtx_trylock(&fp->tx_mtx)) {
482145f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
482245f13123SDavid C Somayajulu 						tx_compl = fp->tx_pkts_completed;
482345f13123SDavid C Somayajulu #endif
482445f13123SDavid C Somayajulu 
4825b284b46dSDavid C Somayajulu 						qlnx_tx_int(ha, fp, fp->txq[tc]);
482645f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
482745f13123SDavid C Somayajulu 						fp->tx_pkts_compl_intr +=
482845f13123SDavid C Somayajulu 							(fp->tx_pkts_completed - tx_compl);
482945f13123SDavid C Somayajulu 						if ((fp->tx_pkts_completed - tx_compl) <= 32)
483045f13123SDavid C Somayajulu 							fp->tx_comInt[0]++;
483145f13123SDavid C Somayajulu 						else if (((fp->tx_pkts_completed - tx_compl) > 32) &&
483245f13123SDavid C Somayajulu 							((fp->tx_pkts_completed - tx_compl) <= 64))
483345f13123SDavid C Somayajulu 							fp->tx_comInt[1]++;
483445f13123SDavid C Somayajulu 						else if(((fp->tx_pkts_completed - tx_compl) > 64) &&
483545f13123SDavid C Somayajulu 							((fp->tx_pkts_completed - tx_compl) <= 128))
483645f13123SDavid C Somayajulu 							fp->tx_comInt[2]++;
483745f13123SDavid C Somayajulu 						else if(((fp->tx_pkts_completed - tx_compl) > 128))
483845f13123SDavid C Somayajulu 							fp->tx_comInt[3]++;
483945f13123SDavid C Somayajulu #endif
4840b284b46dSDavid C Somayajulu 						mtx_unlock(&fp->tx_mtx);
4841b284b46dSDavid C Somayajulu 					}
4842b284b46dSDavid C Somayajulu 				}
484345f13123SDavid C Somayajulu                         }
4844b284b46dSDavid C Somayajulu 
4845b284b46dSDavid C Somayajulu                         rx_int = qlnx_rx_int(ha, fp, ha->rx_pkt_threshold,
4846b284b46dSDavid C Somayajulu                                         lro_enable);
4847b284b46dSDavid C Somayajulu 
4848b284b46dSDavid C Somayajulu                         if (rx_int) {
4849b284b46dSDavid C Somayajulu                                 fp->rx_pkts += rx_int;
48503415775dSJohn Baldwin #ifdef QLNX_SOFT_LRO
4851b284b46dSDavid C Somayajulu                                 total_rx_count += rx_int;
48523415775dSJohn Baldwin #endif
4853b284b46dSDavid C Somayajulu                         }
4854b284b46dSDavid C Somayajulu 
4855b284b46dSDavid C Somayajulu                 } while (rx_int);
4856b284b46dSDavid C Somayajulu 
4857b284b46dSDavid C Somayajulu #ifdef QLNX_SOFT_LRO
4858b284b46dSDavid C Somayajulu                 {
4859b284b46dSDavid C Somayajulu                         struct lro_ctrl *lro;
4860b284b46dSDavid C Somayajulu 
4861b284b46dSDavid C Somayajulu                         lro = &fp->rxq->lro;
4862b284b46dSDavid C Somayajulu 
4863b284b46dSDavid C Somayajulu                         if (lro_enable && total_rx_count) {
4864b284b46dSDavid C Somayajulu 
4865b284b46dSDavid C Somayajulu #ifdef QLNX_TRACE_LRO_CNT
4866b284b46dSDavid C Somayajulu                                 if (lro->lro_mbuf_count & ~1023)
4867b284b46dSDavid C Somayajulu                                         fp->lro_cnt_1024++;
4868b284b46dSDavid C Somayajulu                                 else if (lro->lro_mbuf_count & ~511)
4869b284b46dSDavid C Somayajulu                                         fp->lro_cnt_512++;
4870b284b46dSDavid C Somayajulu                                 else if (lro->lro_mbuf_count & ~255)
4871b284b46dSDavid C Somayajulu                                         fp->lro_cnt_256++;
4872b284b46dSDavid C Somayajulu                                 else if (lro->lro_mbuf_count & ~127)
4873b284b46dSDavid C Somayajulu                                         fp->lro_cnt_128++;
4874b284b46dSDavid C Somayajulu                                 else if (lro->lro_mbuf_count & ~63)
4875b284b46dSDavid C Somayajulu                                         fp->lro_cnt_64++;
4876b284b46dSDavid C Somayajulu #endif /* #ifdef QLNX_TRACE_LRO_CNT */
4877b284b46dSDavid C Somayajulu 
4878b284b46dSDavid C Somayajulu                                 tcp_lro_flush_all(lro);
4879b284b46dSDavid C Somayajulu                         }
4880b284b46dSDavid C Somayajulu                 }
4881b284b46dSDavid C Somayajulu #endif /* #ifdef QLNX_SOFT_LRO */
4882b284b46dSDavid C Somayajulu 
4883b284b46dSDavid C Somayajulu                 ecore_sb_update_sb_idx(fp->sb_info);
4884b284b46dSDavid C Somayajulu                 rmb();
4885b284b46dSDavid C Somayajulu                 ecore_sb_ack(fp->sb_info, IGU_INT_ENABLE, 1);
488611e25f0dSDavid C Somayajulu         }
488711e25f0dSDavid C Somayajulu 
488811e25f0dSDavid C Somayajulu         return;
488911e25f0dSDavid C Somayajulu }
489011e25f0dSDavid C Somayajulu 
489111e25f0dSDavid C Somayajulu /*
489211e25f0dSDavid C Somayajulu  * slow path interrupt processing function
489311e25f0dSDavid C Somayajulu  * can be invoked in polled mode or in interrupt mode via taskqueue.
489411e25f0dSDavid C Somayajulu  */
489511e25f0dSDavid C Somayajulu void
qlnx_sp_isr(void * arg)489611e25f0dSDavid C Somayajulu qlnx_sp_isr(void *arg)
489711e25f0dSDavid C Somayajulu {
489811e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
489911e25f0dSDavid C Somayajulu 	qlnx_host_t		*ha;
490011e25f0dSDavid C Somayajulu 
490111e25f0dSDavid C Somayajulu 	p_hwfn = arg;
490211e25f0dSDavid C Somayajulu 
490311e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)p_hwfn->p_dev;
490411e25f0dSDavid C Somayajulu 
490511e25f0dSDavid C Somayajulu 	ha->sp_interrupts++;
490611e25f0dSDavid C Somayajulu 
49077a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
490811e25f0dSDavid C Somayajulu 
490911e25f0dSDavid C Somayajulu 	ecore_int_sp_dpc(p_hwfn);
491011e25f0dSDavid C Somayajulu 
49117a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
491211e25f0dSDavid C Somayajulu 
491311e25f0dSDavid C Somayajulu 	return;
491411e25f0dSDavid C Somayajulu }
491511e25f0dSDavid C Somayajulu 
491611e25f0dSDavid C Somayajulu /*****************************************************************************
491711e25f0dSDavid C Somayajulu  * Support Functions for DMA'able Memory
491811e25f0dSDavid C Somayajulu  *****************************************************************************/
491911e25f0dSDavid C Somayajulu 
492011e25f0dSDavid C Somayajulu static void
qlnx_dmamap_callback(void * arg,bus_dma_segment_t * segs,int nsegs,int error)492111e25f0dSDavid C Somayajulu qlnx_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
492211e25f0dSDavid C Somayajulu {
492311e25f0dSDavid C Somayajulu         *((bus_addr_t *)arg) = 0;
492411e25f0dSDavid C Somayajulu 
492511e25f0dSDavid C Somayajulu         if (error) {
492611e25f0dSDavid C Somayajulu                 printf("%s: bus_dmamap_load failed (%d)\n", __func__, error);
492711e25f0dSDavid C Somayajulu                 return;
492811e25f0dSDavid C Somayajulu         }
492911e25f0dSDavid C Somayajulu 
493011e25f0dSDavid C Somayajulu         *((bus_addr_t *)arg) = segs[0].ds_addr;
493111e25f0dSDavid C Somayajulu 
493211e25f0dSDavid C Somayajulu         return;
493311e25f0dSDavid C Somayajulu }
493411e25f0dSDavid C Somayajulu 
493511e25f0dSDavid C Somayajulu static int
qlnx_alloc_dmabuf(qlnx_host_t * ha,qlnx_dma_t * dma_buf)493611e25f0dSDavid C Somayajulu qlnx_alloc_dmabuf(qlnx_host_t *ha, qlnx_dma_t *dma_buf)
493711e25f0dSDavid C Somayajulu {
493811e25f0dSDavid C Somayajulu         int             ret = 0;
493911e25f0dSDavid C Somayajulu         bus_addr_t      b_addr;
494011e25f0dSDavid C Somayajulu 
494111e25f0dSDavid C Somayajulu         ret = bus_dma_tag_create(
494211e25f0dSDavid C Somayajulu                         ha->parent_tag,/* parent */
494311e25f0dSDavid C Somayajulu                         dma_buf->alignment,
494411e25f0dSDavid C Somayajulu                         ((bus_size_t)(1ULL << 32)),/* boundary */
494511e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXADDR,      /* lowaddr */
494611e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXADDR,      /* highaddr */
494711e25f0dSDavid C Somayajulu                         NULL, NULL,             /* filter, filterarg */
494811e25f0dSDavid C Somayajulu                         dma_buf->size,          /* maxsize */
494911e25f0dSDavid C Somayajulu                         1,                      /* nsegments */
495011e25f0dSDavid C Somayajulu                         dma_buf->size,          /* maxsegsize */
495111e25f0dSDavid C Somayajulu                         0,                      /* flags */
495211e25f0dSDavid C Somayajulu                         NULL, NULL,             /* lockfunc, lockarg */
495311e25f0dSDavid C Somayajulu                         &dma_buf->dma_tag);
495411e25f0dSDavid C Somayajulu 
495511e25f0dSDavid C Somayajulu         if (ret) {
49567a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "could not create dma tag\n");
495711e25f0dSDavid C Somayajulu                 goto qlnx_alloc_dmabuf_exit;
495811e25f0dSDavid C Somayajulu         }
495911e25f0dSDavid C Somayajulu         ret = bus_dmamem_alloc(dma_buf->dma_tag,
496011e25f0dSDavid C Somayajulu                         (void **)&dma_buf->dma_b,
496111e25f0dSDavid C Somayajulu                         (BUS_DMA_ZERO | BUS_DMA_COHERENT | BUS_DMA_NOWAIT),
496211e25f0dSDavid C Somayajulu                         &dma_buf->dma_map);
496311e25f0dSDavid C Somayajulu         if (ret) {
496411e25f0dSDavid C Somayajulu                 bus_dma_tag_destroy(dma_buf->dma_tag);
49657a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "bus_dmamem_alloc failed\n");
496611e25f0dSDavid C Somayajulu                 goto qlnx_alloc_dmabuf_exit;
496711e25f0dSDavid C Somayajulu         }
496811e25f0dSDavid C Somayajulu 
496911e25f0dSDavid C Somayajulu         ret = bus_dmamap_load(dma_buf->dma_tag,
497011e25f0dSDavid C Somayajulu                         dma_buf->dma_map,
497111e25f0dSDavid C Somayajulu                         dma_buf->dma_b,
497211e25f0dSDavid C Somayajulu                         dma_buf->size,
497311e25f0dSDavid C Somayajulu                         qlnx_dmamap_callback,
497411e25f0dSDavid C Somayajulu                         &b_addr, BUS_DMA_NOWAIT);
497511e25f0dSDavid C Somayajulu 
497611e25f0dSDavid C Somayajulu         if (ret || !b_addr) {
497711e25f0dSDavid C Somayajulu                 bus_dma_tag_destroy(dma_buf->dma_tag);
497811e25f0dSDavid C Somayajulu                 bus_dmamem_free(dma_buf->dma_tag, dma_buf->dma_b,
497911e25f0dSDavid C Somayajulu                         dma_buf->dma_map);
498011e25f0dSDavid C Somayajulu                 ret = -1;
498111e25f0dSDavid C Somayajulu                 goto qlnx_alloc_dmabuf_exit;
498211e25f0dSDavid C Somayajulu         }
498311e25f0dSDavid C Somayajulu 
498411e25f0dSDavid C Somayajulu         dma_buf->dma_addr = b_addr;
498511e25f0dSDavid C Somayajulu 
498611e25f0dSDavid C Somayajulu qlnx_alloc_dmabuf_exit:
498711e25f0dSDavid C Somayajulu 
498811e25f0dSDavid C Somayajulu         return ret;
498911e25f0dSDavid C Somayajulu }
499011e25f0dSDavid C Somayajulu 
499111e25f0dSDavid C Somayajulu static void
qlnx_free_dmabuf(qlnx_host_t * ha,qlnx_dma_t * dma_buf)499211e25f0dSDavid C Somayajulu qlnx_free_dmabuf(qlnx_host_t *ha, qlnx_dma_t *dma_buf)
499311e25f0dSDavid C Somayajulu {
499411e25f0dSDavid C Somayajulu 	bus_dmamap_unload(dma_buf->dma_tag, dma_buf->dma_map);
499511e25f0dSDavid C Somayajulu         bus_dmamem_free(dma_buf->dma_tag, dma_buf->dma_b, dma_buf->dma_map);
499611e25f0dSDavid C Somayajulu         bus_dma_tag_destroy(dma_buf->dma_tag);
499711e25f0dSDavid C Somayajulu 	return;
499811e25f0dSDavid C Somayajulu }
499911e25f0dSDavid C Somayajulu 
500011e25f0dSDavid C Somayajulu void *
qlnx_dma_alloc_coherent(void * ecore_dev,bus_addr_t * phys,uint32_t size)500111e25f0dSDavid C Somayajulu qlnx_dma_alloc_coherent(void *ecore_dev, bus_addr_t *phys, uint32_t size)
500211e25f0dSDavid C Somayajulu {
500311e25f0dSDavid C Somayajulu 	qlnx_dma_t	dma_buf;
500411e25f0dSDavid C Somayajulu 	qlnx_dma_t	*dma_p;
5005eb147f78SJohn Baldwin 	qlnx_host_t	*ha __unused;
500611e25f0dSDavid C Somayajulu 
500711e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)ecore_dev;
500811e25f0dSDavid C Somayajulu 
500911e25f0dSDavid C Somayajulu 	size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
501011e25f0dSDavid C Somayajulu 
501111e25f0dSDavid C Somayajulu 	memset(&dma_buf, 0, sizeof (qlnx_dma_t));
501211e25f0dSDavid C Somayajulu 
501311e25f0dSDavid C Somayajulu 	dma_buf.size = size + PAGE_SIZE;
501411e25f0dSDavid C Somayajulu 	dma_buf.alignment = 8;
501511e25f0dSDavid C Somayajulu 
501611e25f0dSDavid C Somayajulu 	if (qlnx_alloc_dmabuf((qlnx_host_t *)ecore_dev, &dma_buf) != 0)
501711e25f0dSDavid C Somayajulu 		return (NULL);
501811e25f0dSDavid C Somayajulu 	bzero((uint8_t *)dma_buf.dma_b, dma_buf.size);
501911e25f0dSDavid C Somayajulu 
502011e25f0dSDavid C Somayajulu 	*phys = dma_buf.dma_addr;
502111e25f0dSDavid C Somayajulu 
502211e25f0dSDavid C Somayajulu 	dma_p = (qlnx_dma_t *)((uint8_t *)dma_buf.dma_b + size);
502311e25f0dSDavid C Somayajulu 
502411e25f0dSDavid C Somayajulu 	memcpy(dma_p, &dma_buf, sizeof(qlnx_dma_t));
5025217ec208SDavid C Somayajulu 
50267a377fbeSDavid C Somayajulu 	QL_DPRINT5(ha, "[%p %p %p %p 0x%08x ]\n",
502711e25f0dSDavid C Somayajulu 		(void *)dma_buf.dma_map, (void *)dma_buf.dma_tag,
50287a377fbeSDavid C Somayajulu 		dma_buf.dma_b, (void *)dma_buf.dma_addr, size);
5029217ec208SDavid C Somayajulu 
503011e25f0dSDavid C Somayajulu 	return (dma_buf.dma_b);
503111e25f0dSDavid C Somayajulu }
503211e25f0dSDavid C Somayajulu 
503311e25f0dSDavid C Somayajulu void
qlnx_dma_free_coherent(void * ecore_dev,void * v_addr,bus_addr_t phys,uint32_t size)503411e25f0dSDavid C Somayajulu qlnx_dma_free_coherent(void *ecore_dev, void *v_addr, bus_addr_t phys,
503511e25f0dSDavid C Somayajulu 	uint32_t size)
503611e25f0dSDavid C Somayajulu {
503711e25f0dSDavid C Somayajulu 	qlnx_dma_t dma_buf, *dma_p;
503811e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
503911e25f0dSDavid C Somayajulu 
504011e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)ecore_dev;
504111e25f0dSDavid C Somayajulu 
504211e25f0dSDavid C Somayajulu 	if (v_addr == NULL)
504311e25f0dSDavid C Somayajulu 		return;
504411e25f0dSDavid C Somayajulu 
504511e25f0dSDavid C Somayajulu 	size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
504611e25f0dSDavid C Somayajulu 
504711e25f0dSDavid C Somayajulu 	dma_p = (qlnx_dma_t *)((uint8_t *)v_addr + size);
5048217ec208SDavid C Somayajulu 
50497a377fbeSDavid C Somayajulu 	QL_DPRINT5(ha, "[%p %p %p %p 0x%08x ]\n",
505011e25f0dSDavid C Somayajulu 		(void *)dma_p->dma_map, (void *)dma_p->dma_tag,
50517a377fbeSDavid C Somayajulu 		dma_p->dma_b, (void *)dma_p->dma_addr, size);
5052217ec208SDavid C Somayajulu 
505311e25f0dSDavid C Somayajulu 	dma_buf = *dma_p;
505411e25f0dSDavid C Somayajulu 
5055217ec208SDavid C Somayajulu 	if (!ha->qlnxr_debug)
505611e25f0dSDavid C Somayajulu 	qlnx_free_dmabuf((qlnx_host_t *)ecore_dev, &dma_buf);
505711e25f0dSDavid C Somayajulu 	return;
505811e25f0dSDavid C Somayajulu }
505911e25f0dSDavid C Somayajulu 
506011e25f0dSDavid C Somayajulu static int
qlnx_alloc_parent_dma_tag(qlnx_host_t * ha)506111e25f0dSDavid C Somayajulu qlnx_alloc_parent_dma_tag(qlnx_host_t *ha)
506211e25f0dSDavid C Somayajulu {
506311e25f0dSDavid C Somayajulu         int             ret;
506411e25f0dSDavid C Somayajulu         device_t        dev;
506511e25f0dSDavid C Somayajulu 
506611e25f0dSDavid C Somayajulu         dev = ha->pci_dev;
506711e25f0dSDavid C Somayajulu 
506811e25f0dSDavid C Somayajulu         /*
506911e25f0dSDavid C Somayajulu          * Allocate parent DMA Tag
507011e25f0dSDavid C Somayajulu          */
507111e25f0dSDavid C Somayajulu         ret = bus_dma_tag_create(
507211e25f0dSDavid C Somayajulu                         bus_get_dma_tag(dev),   /* parent */
507311e25f0dSDavid C Somayajulu                         1,((bus_size_t)(1ULL << 32)),/* alignment, boundary */
507411e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXADDR,      /* lowaddr */
507511e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXADDR,      /* highaddr */
507611e25f0dSDavid C Somayajulu                         NULL, NULL,             /* filter, filterarg */
507711e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
507811e25f0dSDavid C Somayajulu                         0,                      /* nsegments */
507911e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
508011e25f0dSDavid C Somayajulu                         0,                      /* flags */
508111e25f0dSDavid C Somayajulu                         NULL, NULL,             /* lockfunc, lockarg */
508211e25f0dSDavid C Somayajulu                         &ha->parent_tag);
508311e25f0dSDavid C Somayajulu 
508411e25f0dSDavid C Somayajulu         if (ret) {
50857a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "could not create parent dma tag\n");
508611e25f0dSDavid C Somayajulu                 return (-1);
508711e25f0dSDavid C Somayajulu         }
508811e25f0dSDavid C Somayajulu 
508911e25f0dSDavid C Somayajulu         ha->flags.parent_tag = 1;
509011e25f0dSDavid C Somayajulu 
509111e25f0dSDavid C Somayajulu         return (0);
509211e25f0dSDavid C Somayajulu }
509311e25f0dSDavid C Somayajulu 
509411e25f0dSDavid C Somayajulu static void
qlnx_free_parent_dma_tag(qlnx_host_t * ha)509511e25f0dSDavid C Somayajulu qlnx_free_parent_dma_tag(qlnx_host_t *ha)
509611e25f0dSDavid C Somayajulu {
509711e25f0dSDavid C Somayajulu         if (ha->parent_tag != NULL) {
509811e25f0dSDavid C Somayajulu                 bus_dma_tag_destroy(ha->parent_tag);
509911e25f0dSDavid C Somayajulu 		ha->parent_tag = NULL;
510011e25f0dSDavid C Somayajulu         }
510111e25f0dSDavid C Somayajulu 	return;
510211e25f0dSDavid C Somayajulu }
510311e25f0dSDavid C Somayajulu 
510411e25f0dSDavid C Somayajulu static int
qlnx_alloc_tx_dma_tag(qlnx_host_t * ha)510511e25f0dSDavid C Somayajulu qlnx_alloc_tx_dma_tag(qlnx_host_t *ha)
510611e25f0dSDavid C Somayajulu {
510711e25f0dSDavid C Somayajulu         if (bus_dma_tag_create(NULL,    /* parent */
510811e25f0dSDavid C Somayajulu                 1, 0,    /* alignment, bounds */
510911e25f0dSDavid C Somayajulu                 BUS_SPACE_MAXADDR,       /* lowaddr */
511011e25f0dSDavid C Somayajulu                 BUS_SPACE_MAXADDR,       /* highaddr */
511111e25f0dSDavid C Somayajulu                 NULL, NULL,      /* filter, filterarg */
511211e25f0dSDavid C Somayajulu                 QLNX_MAX_TSO_FRAME_SIZE,     /* maxsize */
511311e25f0dSDavid C Somayajulu                 QLNX_MAX_SEGMENTS,        /* nsegments */
511445f13123SDavid C Somayajulu                 QLNX_MAX_TX_MBUF_SIZE,	  /* maxsegsize */
511545f13123SDavid C Somayajulu                 0,        /* flags */
511611e25f0dSDavid C Somayajulu                 NULL,    /* lockfunc */
511711e25f0dSDavid C Somayajulu                 NULL,    /* lockfuncarg */
511811e25f0dSDavid C Somayajulu                 &ha->tx_tag)) {
51197a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "tx_tag alloc failed\n");
512011e25f0dSDavid C Somayajulu                 return (-1);
512111e25f0dSDavid C Somayajulu         }
512211e25f0dSDavid C Somayajulu 
512311e25f0dSDavid C Somayajulu 	return (0);
512411e25f0dSDavid C Somayajulu }
512511e25f0dSDavid C Somayajulu 
512611e25f0dSDavid C Somayajulu static void
qlnx_free_tx_dma_tag(qlnx_host_t * ha)512711e25f0dSDavid C Somayajulu qlnx_free_tx_dma_tag(qlnx_host_t *ha)
512811e25f0dSDavid C Somayajulu {
512911e25f0dSDavid C Somayajulu         if (ha->tx_tag != NULL) {
513011e25f0dSDavid C Somayajulu                 bus_dma_tag_destroy(ha->tx_tag);
513111e25f0dSDavid C Somayajulu 		ha->tx_tag = NULL;
513211e25f0dSDavid C Somayajulu         }
513311e25f0dSDavid C Somayajulu 	return;
513411e25f0dSDavid C Somayajulu }
513511e25f0dSDavid C Somayajulu 
513611e25f0dSDavid C Somayajulu static int
qlnx_alloc_rx_dma_tag(qlnx_host_t * ha)513711e25f0dSDavid C Somayajulu qlnx_alloc_rx_dma_tag(qlnx_host_t *ha)
513811e25f0dSDavid C Somayajulu {
513911e25f0dSDavid C Somayajulu         if (bus_dma_tag_create(NULL,    /* parent */
514011e25f0dSDavid C Somayajulu                         1, 0,    /* alignment, bounds */
514111e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXADDR,       /* lowaddr */
514211e25f0dSDavid C Somayajulu                         BUS_SPACE_MAXADDR,       /* highaddr */
514311e25f0dSDavid C Somayajulu                         NULL, NULL,      /* filter, filterarg */
514411e25f0dSDavid C Somayajulu                         MJUM9BYTES,     /* maxsize */
514511e25f0dSDavid C Somayajulu                         1,        /* nsegments */
514611e25f0dSDavid C Somayajulu                         MJUM9BYTES,        /* maxsegsize */
514745f13123SDavid C Somayajulu                         0,        /* flags */
514811e25f0dSDavid C Somayajulu                         NULL,    /* lockfunc */
514911e25f0dSDavid C Somayajulu                         NULL,    /* lockfuncarg */
515011e25f0dSDavid C Somayajulu                         &ha->rx_tag)) {
51517a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, " rx_tag alloc failed\n");
515211e25f0dSDavid C Somayajulu 
515311e25f0dSDavid C Somayajulu                 return (-1);
515411e25f0dSDavid C Somayajulu         }
515511e25f0dSDavid C Somayajulu 	return (0);
515611e25f0dSDavid C Somayajulu }
515711e25f0dSDavid C Somayajulu 
515811e25f0dSDavid C Somayajulu static void
qlnx_free_rx_dma_tag(qlnx_host_t * ha)515911e25f0dSDavid C Somayajulu qlnx_free_rx_dma_tag(qlnx_host_t *ha)
516011e25f0dSDavid C Somayajulu {
516111e25f0dSDavid C Somayajulu         if (ha->rx_tag != NULL) {
516211e25f0dSDavid C Somayajulu                 bus_dma_tag_destroy(ha->rx_tag);
516311e25f0dSDavid C Somayajulu 		ha->rx_tag = NULL;
516411e25f0dSDavid C Somayajulu         }
516511e25f0dSDavid C Somayajulu 	return;
516611e25f0dSDavid C Somayajulu }
516711e25f0dSDavid C Somayajulu 
516811e25f0dSDavid C Somayajulu /*********************************
516911e25f0dSDavid C Somayajulu  * Exported functions
517011e25f0dSDavid C Somayajulu  *********************************/
517111e25f0dSDavid C Somayajulu uint32_t
qlnx_pci_bus_get_bar_size(void * ecore_dev,uint8_t bar_id)517211e25f0dSDavid C Somayajulu qlnx_pci_bus_get_bar_size(void *ecore_dev, uint8_t bar_id)
517311e25f0dSDavid C Somayajulu {
517411e25f0dSDavid C Somayajulu 	uint32_t bar_size;
517511e25f0dSDavid C Somayajulu 
517611e25f0dSDavid C Somayajulu 	bar_id = bar_id * 2;
517711e25f0dSDavid C Somayajulu 
517811e25f0dSDavid C Somayajulu 	bar_size = bus_get_resource_count(((qlnx_host_t *)ecore_dev)->pci_dev,
517911e25f0dSDavid C Somayajulu 				SYS_RES_MEMORY,
518011e25f0dSDavid C Somayajulu 				PCIR_BAR(bar_id));
518111e25f0dSDavid C Somayajulu 
518211e25f0dSDavid C Somayajulu 	return (bar_size);
518311e25f0dSDavid C Somayajulu }
518411e25f0dSDavid C Somayajulu 
518511e25f0dSDavid C Somayajulu uint32_t
qlnx_pci_read_config_byte(void * ecore_dev,uint32_t pci_reg,uint8_t * reg_value)518611e25f0dSDavid C Somayajulu qlnx_pci_read_config_byte(void *ecore_dev, uint32_t pci_reg, uint8_t *reg_value)
518711e25f0dSDavid C Somayajulu {
518811e25f0dSDavid C Somayajulu 	*reg_value = pci_read_config(((qlnx_host_t *)ecore_dev)->pci_dev,
518911e25f0dSDavid C Somayajulu 				pci_reg, 1);
519011e25f0dSDavid C Somayajulu 	return 0;
519111e25f0dSDavid C Somayajulu }
519211e25f0dSDavid C Somayajulu 
519311e25f0dSDavid C Somayajulu uint32_t
qlnx_pci_read_config_word(void * ecore_dev,uint32_t pci_reg,uint16_t * reg_value)519411e25f0dSDavid C Somayajulu qlnx_pci_read_config_word(void *ecore_dev, uint32_t pci_reg,
519511e25f0dSDavid C Somayajulu 	uint16_t *reg_value)
519611e25f0dSDavid C Somayajulu {
519711e25f0dSDavid C Somayajulu 	*reg_value = pci_read_config(((qlnx_host_t *)ecore_dev)->pci_dev,
519811e25f0dSDavid C Somayajulu 				pci_reg, 2);
519911e25f0dSDavid C Somayajulu 	return 0;
520011e25f0dSDavid C Somayajulu }
520111e25f0dSDavid C Somayajulu 
520211e25f0dSDavid C Somayajulu uint32_t
qlnx_pci_read_config_dword(void * ecore_dev,uint32_t pci_reg,uint32_t * reg_value)520311e25f0dSDavid C Somayajulu qlnx_pci_read_config_dword(void *ecore_dev, uint32_t pci_reg,
520411e25f0dSDavid C Somayajulu 	uint32_t *reg_value)
520511e25f0dSDavid C Somayajulu {
520611e25f0dSDavid C Somayajulu 	*reg_value = pci_read_config(((qlnx_host_t *)ecore_dev)->pci_dev,
520711e25f0dSDavid C Somayajulu 				pci_reg, 4);
520811e25f0dSDavid C Somayajulu 	return 0;
520911e25f0dSDavid C Somayajulu }
521011e25f0dSDavid C Somayajulu 
521111e25f0dSDavid C Somayajulu void
qlnx_pci_write_config_byte(void * ecore_dev,uint32_t pci_reg,uint8_t reg_value)521211e25f0dSDavid C Somayajulu qlnx_pci_write_config_byte(void *ecore_dev, uint32_t pci_reg, uint8_t reg_value)
521311e25f0dSDavid C Somayajulu {
521411e25f0dSDavid C Somayajulu 	pci_write_config(((qlnx_host_t *)ecore_dev)->pci_dev,
521511e25f0dSDavid C Somayajulu 		pci_reg, reg_value, 1);
521611e25f0dSDavid C Somayajulu 	return;
521711e25f0dSDavid C Somayajulu }
521811e25f0dSDavid C Somayajulu 
521911e25f0dSDavid C Somayajulu void
qlnx_pci_write_config_word(void * ecore_dev,uint32_t pci_reg,uint16_t reg_value)522011e25f0dSDavid C Somayajulu qlnx_pci_write_config_word(void *ecore_dev, uint32_t pci_reg,
522111e25f0dSDavid C Somayajulu 	uint16_t reg_value)
522211e25f0dSDavid C Somayajulu {
522311e25f0dSDavid C Somayajulu 	pci_write_config(((qlnx_host_t *)ecore_dev)->pci_dev,
522411e25f0dSDavid C Somayajulu 		pci_reg, reg_value, 2);
522511e25f0dSDavid C Somayajulu 	return;
522611e25f0dSDavid C Somayajulu }
522711e25f0dSDavid C Somayajulu 
522811e25f0dSDavid C Somayajulu void
qlnx_pci_write_config_dword(void * ecore_dev,uint32_t pci_reg,uint32_t reg_value)522911e25f0dSDavid C Somayajulu qlnx_pci_write_config_dword(void *ecore_dev, uint32_t pci_reg,
523011e25f0dSDavid C Somayajulu 	uint32_t reg_value)
523111e25f0dSDavid C Somayajulu {
523211e25f0dSDavid C Somayajulu 	pci_write_config(((qlnx_host_t *)ecore_dev)->pci_dev,
523311e25f0dSDavid C Somayajulu 		pci_reg, reg_value, 4);
523411e25f0dSDavid C Somayajulu 	return;
523511e25f0dSDavid C Somayajulu }
523611e25f0dSDavid C Somayajulu 
523711e25f0dSDavid C Somayajulu int
qlnx_pci_find_capability(void * ecore_dev,int cap)523811e25f0dSDavid C Somayajulu qlnx_pci_find_capability(void *ecore_dev, int cap)
523911e25f0dSDavid C Somayajulu {
524011e25f0dSDavid C Somayajulu 	int		reg;
52417a377fbeSDavid C Somayajulu 	qlnx_host_t	*ha;
524211e25f0dSDavid C Somayajulu 
52437a377fbeSDavid C Somayajulu 	ha = ecore_dev;
52447a377fbeSDavid C Somayajulu 
52457a377fbeSDavid C Somayajulu 	if (pci_find_cap(ha->pci_dev, PCIY_EXPRESS, &reg) == 0)
524611e25f0dSDavid C Somayajulu 		return reg;
524711e25f0dSDavid C Somayajulu 	else {
52487a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "failed\n");
524911e25f0dSDavid C Somayajulu 		return 0;
525011e25f0dSDavid C Somayajulu 	}
525111e25f0dSDavid C Somayajulu }
525211e25f0dSDavid C Somayajulu 
5253217ec208SDavid C Somayajulu int
qlnx_pci_find_ext_capability(void * ecore_dev,int ext_cap)5254217ec208SDavid C Somayajulu qlnx_pci_find_ext_capability(void *ecore_dev, int ext_cap)
5255217ec208SDavid C Somayajulu {
5256217ec208SDavid C Somayajulu 	int		reg;
5257217ec208SDavid C Somayajulu 	qlnx_host_t	*ha;
5258217ec208SDavid C Somayajulu 
5259217ec208SDavid C Somayajulu 	ha = ecore_dev;
5260217ec208SDavid C Somayajulu 
5261217ec208SDavid C Somayajulu 	if (pci_find_extcap(ha->pci_dev, ext_cap, &reg) == 0)
5262217ec208SDavid C Somayajulu 		return reg;
5263217ec208SDavid C Somayajulu 	else {
5264217ec208SDavid C Somayajulu 		QL_DPRINT1(ha, "failed\n");
5265217ec208SDavid C Somayajulu 		return 0;
5266217ec208SDavid C Somayajulu 	}
5267217ec208SDavid C Somayajulu }
5268217ec208SDavid C Somayajulu 
526911e25f0dSDavid C Somayajulu uint32_t
qlnx_reg_rd32(void * hwfn,uint32_t reg_addr)527011e25f0dSDavid C Somayajulu qlnx_reg_rd32(void *hwfn, uint32_t reg_addr)
527111e25f0dSDavid C Somayajulu {
527211e25f0dSDavid C Somayajulu 	uint32_t		data32;
527311e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
527411e25f0dSDavid C Somayajulu 
527511e25f0dSDavid C Somayajulu 	p_hwfn = hwfn;
527611e25f0dSDavid C Somayajulu 
5277217ec208SDavid C Somayajulu 	data32 = bus_read_4(((qlnx_host_t *)p_hwfn->p_dev)->pci_reg, \
5278217ec208SDavid C Somayajulu 			(bus_size_t)(p_hwfn->reg_offset + reg_addr));
527911e25f0dSDavid C Somayajulu 
528011e25f0dSDavid C Somayajulu 	return (data32);
528111e25f0dSDavid C Somayajulu }
528211e25f0dSDavid C Somayajulu 
528311e25f0dSDavid C Somayajulu void
qlnx_reg_wr32(void * hwfn,uint32_t reg_addr,uint32_t value)528411e25f0dSDavid C Somayajulu qlnx_reg_wr32(void *hwfn, uint32_t reg_addr, uint32_t value)
528511e25f0dSDavid C Somayajulu {
5286217ec208SDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn = hwfn;
528711e25f0dSDavid C Somayajulu 
5288217ec208SDavid C Somayajulu 	bus_write_4(((qlnx_host_t *)p_hwfn->p_dev)->pci_reg, \
5289217ec208SDavid C Somayajulu 		(bus_size_t)(p_hwfn->reg_offset + reg_addr), value);
529011e25f0dSDavid C Somayajulu 
529111e25f0dSDavid C Somayajulu 	return;
529211e25f0dSDavid C Somayajulu }
529311e25f0dSDavid C Somayajulu 
529411e25f0dSDavid C Somayajulu void
qlnx_reg_wr16(void * hwfn,uint32_t reg_addr,uint16_t value)529511e25f0dSDavid C Somayajulu qlnx_reg_wr16(void *hwfn, uint32_t reg_addr, uint16_t value)
529611e25f0dSDavid C Somayajulu {
5297217ec208SDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn = hwfn;
5298217ec208SDavid C Somayajulu 
5299217ec208SDavid C Somayajulu 	bus_write_2(((qlnx_host_t *)p_hwfn->p_dev)->pci_reg, \
5300217ec208SDavid C Somayajulu 		(bus_size_t)(p_hwfn->reg_offset + reg_addr), value);
5301217ec208SDavid C Somayajulu 	return;
5302217ec208SDavid C Somayajulu }
5303217ec208SDavid C Somayajulu 
5304217ec208SDavid C Somayajulu void
qlnx_dbell_wr32_db(void * hwfn,void * reg_addr,uint32_t value)5305217ec208SDavid C Somayajulu qlnx_dbell_wr32_db(void *hwfn, void *reg_addr, uint32_t value)
5306217ec208SDavid C Somayajulu {
530711e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
530811e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
5309217ec208SDavid C Somayajulu 	uint32_t	offset;
531011e25f0dSDavid C Somayajulu 
531111e25f0dSDavid C Somayajulu 	p_hwfn = hwfn;
531211e25f0dSDavid C Somayajulu 
531311e25f0dSDavid C Somayajulu 	cdev = p_hwfn->p_dev;
531411e25f0dSDavid C Somayajulu 
5315217ec208SDavid C Somayajulu 	offset = (uint32_t)((uint8_t *)reg_addr - (uint8_t *)(p_hwfn->doorbells));
5316217ec208SDavid C Somayajulu 	bus_write_4(((qlnx_host_t *)cdev)->pci_dbells, offset, value);
531711e25f0dSDavid C Somayajulu 
531811e25f0dSDavid C Somayajulu 	return;
531911e25f0dSDavid C Somayajulu }
532011e25f0dSDavid C Somayajulu 
532111e25f0dSDavid C Somayajulu void
qlnx_dbell_wr32(void * hwfn,uint32_t reg_addr,uint32_t value)532211e25f0dSDavid C Somayajulu qlnx_dbell_wr32(void *hwfn, uint32_t reg_addr, uint32_t value)
532311e25f0dSDavid C Somayajulu {
5324217ec208SDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn = hwfn;
532511e25f0dSDavid C Somayajulu 
5326217ec208SDavid C Somayajulu 	bus_write_4(((qlnx_host_t *)p_hwfn->p_dev)->pci_dbells, \
5327217ec208SDavid C Somayajulu 		(bus_size_t)(p_hwfn->db_offset + reg_addr), value);
532811e25f0dSDavid C Somayajulu 
532911e25f0dSDavid C Somayajulu 	return;
533011e25f0dSDavid C Somayajulu }
533111e25f0dSDavid C Somayajulu 
533211e25f0dSDavid C Somayajulu uint32_t
qlnx_direct_reg_rd32(void * p_hwfn,uint32_t * reg_addr)533311e25f0dSDavid C Somayajulu qlnx_direct_reg_rd32(void *p_hwfn, uint32_t *reg_addr)
533411e25f0dSDavid C Somayajulu {
533511e25f0dSDavid C Somayajulu 	uint32_t		data32;
5336217ec208SDavid C Somayajulu 	bus_size_t		offset;
533711e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
533811e25f0dSDavid C Somayajulu 
533911e25f0dSDavid C Somayajulu 	cdev = ((struct ecore_hwfn *)p_hwfn)->p_dev;
5340217ec208SDavid C Somayajulu 	offset = (bus_size_t)((uint8_t *)reg_addr - (uint8_t *)(cdev->regview));
534111e25f0dSDavid C Somayajulu 
534211e25f0dSDavid C Somayajulu 	data32 = bus_read_4(((qlnx_host_t *)cdev)->pci_reg, offset);
534311e25f0dSDavid C Somayajulu 
534411e25f0dSDavid C Somayajulu 	return (data32);
534511e25f0dSDavid C Somayajulu }
534611e25f0dSDavid C Somayajulu 
534711e25f0dSDavid C Somayajulu void
qlnx_direct_reg_wr32(void * p_hwfn,void * reg_addr,uint32_t value)534811e25f0dSDavid C Somayajulu qlnx_direct_reg_wr32(void *p_hwfn, void *reg_addr, uint32_t value)
534911e25f0dSDavid C Somayajulu {
5350217ec208SDavid C Somayajulu 	bus_size_t		offset;
535111e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
535211e25f0dSDavid C Somayajulu 
535311e25f0dSDavid C Somayajulu 	cdev = ((struct ecore_hwfn *)p_hwfn)->p_dev;
5354217ec208SDavid C Somayajulu 	offset = (bus_size_t)((uint8_t *)reg_addr - (uint8_t *)(cdev->regview));
535511e25f0dSDavid C Somayajulu 
535611e25f0dSDavid C Somayajulu 	bus_write_4(((qlnx_host_t *)cdev)->pci_reg, offset, value);
535711e25f0dSDavid C Somayajulu 
535811e25f0dSDavid C Somayajulu 	return;
535911e25f0dSDavid C Somayajulu }
536011e25f0dSDavid C Somayajulu 
53619efd0ba7SDavid C Somayajulu void
qlnx_direct_reg_wr64(void * p_hwfn,void * reg_addr,uint64_t value)53629efd0ba7SDavid C Somayajulu qlnx_direct_reg_wr64(void *p_hwfn, void *reg_addr, uint64_t value)
53639efd0ba7SDavid C Somayajulu {
5364217ec208SDavid C Somayajulu 	bus_size_t		offset;
53659efd0ba7SDavid C Somayajulu 	struct ecore_dev	*cdev;
53669efd0ba7SDavid C Somayajulu 
53679efd0ba7SDavid C Somayajulu 	cdev = ((struct ecore_hwfn *)p_hwfn)->p_dev;
5368217ec208SDavid C Somayajulu 	offset = (bus_size_t)((uint8_t *)reg_addr - (uint8_t *)(cdev->regview));
53699efd0ba7SDavid C Somayajulu 
53709efd0ba7SDavid C Somayajulu 	bus_write_8(((qlnx_host_t *)cdev)->pci_reg, offset, value);
53719efd0ba7SDavid C Somayajulu 	return;
53729efd0ba7SDavid C Somayajulu }
53739efd0ba7SDavid C Somayajulu 
537411e25f0dSDavid C Somayajulu void *
qlnx_zalloc(uint32_t size)537511e25f0dSDavid C Somayajulu qlnx_zalloc(uint32_t size)
537611e25f0dSDavid C Somayajulu {
537711e25f0dSDavid C Somayajulu 	caddr_t	va;
537811e25f0dSDavid C Somayajulu 
537911e25f0dSDavid C Somayajulu 	va = malloc((unsigned long)size, M_QLNXBUF, M_NOWAIT);
538011e25f0dSDavid C Somayajulu 	bzero(va, size);
538111e25f0dSDavid C Somayajulu 	return ((void *)va);
538211e25f0dSDavid C Somayajulu }
538311e25f0dSDavid C Somayajulu 
538411e25f0dSDavid C Somayajulu void
qlnx_barrier(void * p_dev)53851c45a62aSKeith Reynolds qlnx_barrier(void *p_dev)
538611e25f0dSDavid C Somayajulu {
538711e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
538811e25f0dSDavid C Somayajulu 
53891c45a62aSKeith Reynolds 	ha = ((struct ecore_dev *) p_dev)->ha;
539011e25f0dSDavid C Somayajulu 	bus_barrier(ha->pci_reg,  0, 0, BUS_SPACE_BARRIER_WRITE);
539111e25f0dSDavid C Somayajulu }
539211e25f0dSDavid C Somayajulu 
539311e25f0dSDavid C Somayajulu void
qlnx_link_update(void * p_hwfn)539411e25f0dSDavid C Somayajulu qlnx_link_update(void *p_hwfn)
539511e25f0dSDavid C Somayajulu {
539611e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
539711e25f0dSDavid C Somayajulu 	int		prev_link_state;
539811e25f0dSDavid C Somayajulu 
539911e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)((struct ecore_hwfn *)p_hwfn)->p_dev;
540011e25f0dSDavid C Somayajulu 
5401217ec208SDavid C Somayajulu 	qlnx_fill_link(ha, p_hwfn, &ha->if_link);
540211e25f0dSDavid C Somayajulu 
540311e25f0dSDavid C Somayajulu 	prev_link_state = ha->link_up;
540411e25f0dSDavid C Somayajulu 	ha->link_up = ha->if_link.link_up;
540511e25f0dSDavid C Somayajulu 
540611e25f0dSDavid C Somayajulu         if (prev_link_state !=  ha->link_up) {
540711e25f0dSDavid C Somayajulu                 if (ha->link_up) {
540811e25f0dSDavid C Somayajulu                         if_link_state_change(ha->ifp, LINK_STATE_UP);
540911e25f0dSDavid C Somayajulu                 } else {
541011e25f0dSDavid C Somayajulu                         if_link_state_change(ha->ifp, LINK_STATE_DOWN);
541111e25f0dSDavid C Somayajulu                 }
541211e25f0dSDavid C Somayajulu         }
5413217ec208SDavid C Somayajulu #ifndef QLNX_VF
5414217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
5415217ec208SDavid C Somayajulu 
5416217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
5417217ec208SDavid C Somayajulu 		if (ha->sriov_initialized)
5418217ec208SDavid C Somayajulu 			qlnx_inform_vf_link_state(p_hwfn, ha);
5419217ec208SDavid C Somayajulu 	}
5420217ec208SDavid C Somayajulu 
5421217ec208SDavid C Somayajulu #endif /* #ifdef CONFIG_ECORE_SRIOV */
5422217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_VF */
5423217ec208SDavid C Somayajulu 
5424217ec208SDavid C Somayajulu         return;
5425217ec208SDavid C Somayajulu }
5426217ec208SDavid C Somayajulu 
5427217ec208SDavid C Somayajulu static void
__qlnx_osal_vf_fill_acquire_resc_req(struct ecore_hwfn * p_hwfn,struct ecore_vf_acquire_sw_info * p_sw_info)5428217ec208SDavid C Somayajulu __qlnx_osal_vf_fill_acquire_resc_req(struct ecore_hwfn *p_hwfn,
5429217ec208SDavid C Somayajulu 	struct ecore_vf_acquire_sw_info *p_sw_info)
5430217ec208SDavid C Somayajulu {
5431217ec208SDavid C Somayajulu 	p_sw_info->driver_version = (QLNX_VERSION_MAJOR << 24) |
5432217ec208SDavid C Somayajulu 					(QLNX_VERSION_MINOR << 16) |
5433217ec208SDavid C Somayajulu 					 QLNX_VERSION_BUILD;
5434217ec208SDavid C Somayajulu 	p_sw_info->os_type = VFPF_ACQUIRE_OS_FREEBSD;
5435217ec208SDavid C Somayajulu 
543611e25f0dSDavid C Somayajulu 	return;
543711e25f0dSDavid C Somayajulu }
543811e25f0dSDavid C Somayajulu 
543911e25f0dSDavid C Somayajulu void
qlnx_osal_vf_fill_acquire_resc_req(void * p_hwfn,void * p_resc_req,void * p_sw_info)5440217ec208SDavid C Somayajulu qlnx_osal_vf_fill_acquire_resc_req(void *p_hwfn, void *p_resc_req,
5441217ec208SDavid C Somayajulu 	void *p_sw_info)
5442217ec208SDavid C Somayajulu {
5443217ec208SDavid C Somayajulu 	__qlnx_osal_vf_fill_acquire_resc_req(p_hwfn, p_sw_info);
5444217ec208SDavid C Somayajulu 
5445217ec208SDavid C Somayajulu 	return;
5446217ec208SDavid C Somayajulu }
5447217ec208SDavid C Somayajulu 
5448217ec208SDavid C Somayajulu void
qlnx_fill_link(qlnx_host_t * ha,struct ecore_hwfn * hwfn,struct qlnx_link_output * if_link)5449217ec208SDavid C Somayajulu qlnx_fill_link(qlnx_host_t *ha, struct ecore_hwfn *hwfn,
5450217ec208SDavid C Somayajulu 	struct qlnx_link_output *if_link)
545111e25f0dSDavid C Somayajulu {
545211e25f0dSDavid C Somayajulu 	struct ecore_mcp_link_params    link_params;
545311e25f0dSDavid C Somayajulu 	struct ecore_mcp_link_state     link_state;
5454217ec208SDavid C Somayajulu 	uint8_t				p_change;
5455217ec208SDavid C Somayajulu 	struct ecore_ptt *p_ptt = NULL;
5456217ec208SDavid C Somayajulu 
545711e25f0dSDavid C Somayajulu 	memset(if_link, 0, sizeof(*if_link));
545811e25f0dSDavid C Somayajulu 	memset(&link_params, 0, sizeof(struct ecore_mcp_link_params));
545911e25f0dSDavid C Somayajulu 	memset(&link_state, 0, sizeof(struct ecore_mcp_link_state));
546011e25f0dSDavid C Somayajulu 
5461217ec208SDavid C Somayajulu 	ha = (qlnx_host_t *)hwfn->p_dev;
5462217ec208SDavid C Somayajulu 
546311e25f0dSDavid C Somayajulu 	/* Prepare source inputs */
546411e25f0dSDavid C Somayajulu 	/* we only deal with physical functions */
5465217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
5466217ec208SDavid C Somayajulu         	p_ptt = ecore_ptt_acquire(hwfn);
5467217ec208SDavid C Somayajulu 
5468217ec208SDavid C Somayajulu 	        if (p_ptt == NULL) {
5469217ec208SDavid C Somayajulu 			QL_DPRINT1(ha, "ecore_ptt_acquire failed\n");
5470217ec208SDavid C Somayajulu 			return;
5471217ec208SDavid C Somayajulu 		}
5472217ec208SDavid C Somayajulu 
5473217ec208SDavid C Somayajulu 		ecore_mcp_get_media_type(hwfn, p_ptt, &if_link->media_type);
5474217ec208SDavid C Somayajulu 		ecore_ptt_release(hwfn, p_ptt);
5475217ec208SDavid C Somayajulu 
547611e25f0dSDavid C Somayajulu 		memcpy(&link_params, ecore_mcp_get_link_params(hwfn),
547711e25f0dSDavid C Somayajulu 			sizeof(link_params));
547811e25f0dSDavid C Somayajulu 		memcpy(&link_state, ecore_mcp_get_link_state(hwfn),
547911e25f0dSDavid C Somayajulu 			sizeof(link_state));
5480217ec208SDavid C Somayajulu 	} else {
5481217ec208SDavid C Somayajulu 		ecore_mcp_get_media_type(hwfn, NULL, &if_link->media_type);
5482217ec208SDavid C Somayajulu 		ecore_vf_read_bulletin(hwfn, &p_change);
5483217ec208SDavid C Somayajulu 		ecore_vf_get_link_params(hwfn, &link_params);
5484217ec208SDavid C Somayajulu 		ecore_vf_get_link_state(hwfn, &link_state);
5485217ec208SDavid C Somayajulu 	}
548611e25f0dSDavid C Somayajulu 
548711e25f0dSDavid C Somayajulu 	/* Set the link parameters to pass to protocol driver */
548811e25f0dSDavid C Somayajulu 	if (link_state.link_up) {
548911e25f0dSDavid C Somayajulu 		if_link->link_up = true;
549011e25f0dSDavid C Somayajulu 		if_link->speed = link_state.speed;
549111e25f0dSDavid C Somayajulu 	}
549211e25f0dSDavid C Somayajulu 
549311e25f0dSDavid C Somayajulu 	if_link->supported_caps = QLNX_LINK_CAP_FIBRE;
549411e25f0dSDavid C Somayajulu 
549511e25f0dSDavid C Somayajulu 	if (link_params.speed.autoneg)
549611e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_Autoneg;
549711e25f0dSDavid C Somayajulu 
549811e25f0dSDavid C Somayajulu 	if (link_params.pause.autoneg ||
549911e25f0dSDavid C Somayajulu 		(link_params.pause.forced_rx && link_params.pause.forced_tx))
550011e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_Asym_Pause;
550111e25f0dSDavid C Somayajulu 
550211e25f0dSDavid C Somayajulu 	if (link_params.pause.autoneg || link_params.pause.forced_rx ||
550311e25f0dSDavid C Somayajulu 		link_params.pause.forced_tx)
550411e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_Pause;
550511e25f0dSDavid C Somayajulu 
550611e25f0dSDavid C Somayajulu 	if (link_params.speed.advertised_speeds &
550711e25f0dSDavid C Somayajulu 		NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
550811e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_1000baseT_Half |
550911e25f0dSDavid C Somayajulu                                            QLNX_LINK_CAP_1000baseT_Full;
551011e25f0dSDavid C Somayajulu 
551111e25f0dSDavid C Somayajulu 	if (link_params.speed.advertised_speeds &
551211e25f0dSDavid C Somayajulu 		NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
551311e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_10000baseKR_Full;
551411e25f0dSDavid C Somayajulu 
551511e25f0dSDavid C Somayajulu 	if (link_params.speed.advertised_speeds &
551611e25f0dSDavid C Somayajulu 		NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
551711e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_25000baseKR_Full;
551811e25f0dSDavid C Somayajulu 
551911e25f0dSDavid C Somayajulu 	if (link_params.speed.advertised_speeds &
552011e25f0dSDavid C Somayajulu 		NVM_CFG1_PORT_DRV_LINK_SPEED_40G)
552111e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_40000baseLR4_Full;
552211e25f0dSDavid C Somayajulu 
552311e25f0dSDavid C Somayajulu 	if (link_params.speed.advertised_speeds &
552411e25f0dSDavid C Somayajulu 		NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
552511e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_50000baseKR2_Full;
552611e25f0dSDavid C Somayajulu 
552711e25f0dSDavid C Somayajulu 	if (link_params.speed.advertised_speeds &
552811e25f0dSDavid C Somayajulu 		NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
552911e25f0dSDavid C Somayajulu 		if_link->supported_caps |= QLNX_LINK_CAP_100000baseKR4_Full;
553011e25f0dSDavid C Somayajulu 
553111e25f0dSDavid C Somayajulu 	if_link->advertised_caps = if_link->supported_caps;
553211e25f0dSDavid C Somayajulu 
553311e25f0dSDavid C Somayajulu 	if_link->autoneg = link_params.speed.autoneg;
553411e25f0dSDavid C Somayajulu 	if_link->duplex = QLNX_LINK_DUPLEX;
553511e25f0dSDavid C Somayajulu 
553611e25f0dSDavid C Somayajulu 	/* Link partner capabilities */
553711e25f0dSDavid C Somayajulu 
553811e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_1G_HD)
553911e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_1000baseT_Half;
554011e25f0dSDavid C Somayajulu 
554111e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_1G_FD)
554211e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_1000baseT_Full;
554311e25f0dSDavid C Somayajulu 
554411e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_10G)
554511e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_10000baseKR_Full;
554611e25f0dSDavid C Somayajulu 
554711e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_25G)
554811e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_25000baseKR_Full;
554911e25f0dSDavid C Somayajulu 
555011e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_40G)
555111e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_40000baseLR4_Full;
555211e25f0dSDavid C Somayajulu 
555311e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_50G)
555411e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_50000baseKR2_Full;
555511e25f0dSDavid C Somayajulu 
555611e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_speed & ECORE_LINK_PARTNER_SPEED_100G)
555711e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_100000baseKR4_Full;
555811e25f0dSDavid C Somayajulu 
555911e25f0dSDavid C Somayajulu 	if (link_state.an_complete)
556011e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_Autoneg;
556111e25f0dSDavid C Somayajulu 
556211e25f0dSDavid C Somayajulu 	if (link_state.partner_adv_pause)
556311e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_Pause;
556411e25f0dSDavid C Somayajulu 
556511e25f0dSDavid C Somayajulu 	if ((link_state.partner_adv_pause ==
556611e25f0dSDavid C Somayajulu 		ECORE_LINK_PARTNER_ASYMMETRIC_PAUSE) ||
556711e25f0dSDavid C Somayajulu 		(link_state.partner_adv_pause ==
556811e25f0dSDavid C Somayajulu 			ECORE_LINK_PARTNER_BOTH_PAUSE))
556911e25f0dSDavid C Somayajulu 		if_link->link_partner_caps |= QLNX_LINK_CAP_Asym_Pause;
557011e25f0dSDavid C Somayajulu 
557111e25f0dSDavid C Somayajulu 	return;
557211e25f0dSDavid C Somayajulu }
557311e25f0dSDavid C Somayajulu 
5574217ec208SDavid C Somayajulu void
qlnx_schedule_recovery(void * p_hwfn)5575217ec208SDavid C Somayajulu qlnx_schedule_recovery(void *p_hwfn)
5576217ec208SDavid C Somayajulu {
5577217ec208SDavid C Somayajulu 	qlnx_host_t	*ha;
5578217ec208SDavid C Somayajulu 
5579217ec208SDavid C Somayajulu 	ha = (qlnx_host_t *)((struct ecore_hwfn *)p_hwfn)->p_dev;
5580217ec208SDavid C Somayajulu 
5581217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
5582217ec208SDavid C Somayajulu 		taskqueue_enqueue(ha->err_taskqueue, &ha->err_task);
5583217ec208SDavid C Somayajulu 	}
5584217ec208SDavid C Somayajulu 
5585217ec208SDavid C Somayajulu 	return;
5586217ec208SDavid C Somayajulu }
5587217ec208SDavid C Somayajulu 
558811e25f0dSDavid C Somayajulu static int
qlnx_nic_setup(struct ecore_dev * cdev,struct ecore_pf_params * func_params)558911e25f0dSDavid C Somayajulu qlnx_nic_setup(struct ecore_dev *cdev, struct ecore_pf_params *func_params)
559011e25f0dSDavid C Somayajulu {
559111e25f0dSDavid C Somayajulu         int	rc, i;
559211e25f0dSDavid C Somayajulu 
559311e25f0dSDavid C Somayajulu         for (i = 0; i < cdev->num_hwfns; i++) {
559411e25f0dSDavid C Somayajulu                 struct ecore_hwfn *p_hwfn = &cdev->hwfns[i];
559511e25f0dSDavid C Somayajulu                 p_hwfn->pf_params = *func_params;
5596217ec208SDavid C Somayajulu 
5597217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
5598217ec208SDavid C Somayajulu 		if (qlnx_vf_device((qlnx_host_t *)cdev) != 0) {
5599217ec208SDavid C Somayajulu 			p_hwfn->using_ll2 = true;
5600217ec208SDavid C Somayajulu 		}
5601217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
560211e25f0dSDavid C Somayajulu         }
560311e25f0dSDavid C Somayajulu 
560411e25f0dSDavid C Somayajulu         rc = ecore_resc_alloc(cdev);
560511e25f0dSDavid C Somayajulu         if (rc)
560611e25f0dSDavid C Somayajulu                 goto qlnx_nic_setup_exit;
560711e25f0dSDavid C Somayajulu 
560811e25f0dSDavid C Somayajulu         ecore_resc_setup(cdev);
560911e25f0dSDavid C Somayajulu 
561011e25f0dSDavid C Somayajulu qlnx_nic_setup_exit:
561111e25f0dSDavid C Somayajulu 
561211e25f0dSDavid C Somayajulu         return rc;
561311e25f0dSDavid C Somayajulu }
561411e25f0dSDavid C Somayajulu 
561511e25f0dSDavid C Somayajulu static int
qlnx_nic_start(struct ecore_dev * cdev)561611e25f0dSDavid C Somayajulu qlnx_nic_start(struct ecore_dev *cdev)
561711e25f0dSDavid C Somayajulu {
561811e25f0dSDavid C Somayajulu         int				rc;
561911e25f0dSDavid C Somayajulu 	struct ecore_hw_init_params	params;
562011e25f0dSDavid C Somayajulu 
562111e25f0dSDavid C Somayajulu 	bzero(&params, sizeof (struct ecore_hw_init_params));
562211e25f0dSDavid C Somayajulu 
562311e25f0dSDavid C Somayajulu 	params.p_tunn = NULL;
562411e25f0dSDavid C Somayajulu 	params.b_hw_start = true;
562511e25f0dSDavid C Somayajulu 	params.int_mode = cdev->int_mode;
562611e25f0dSDavid C Somayajulu 	params.allow_npar_tx_switch = true;
562711e25f0dSDavid C Somayajulu 	params.bin_fw_data = NULL;
562811e25f0dSDavid C Somayajulu 
562911e25f0dSDavid C Somayajulu         rc = ecore_hw_init(cdev, &params);
563011e25f0dSDavid C Somayajulu         if (rc) {
563111e25f0dSDavid C Somayajulu                 ecore_resc_free(cdev);
563211e25f0dSDavid C Somayajulu                 return rc;
563311e25f0dSDavid C Somayajulu         }
563411e25f0dSDavid C Somayajulu 
563511e25f0dSDavid C Somayajulu         return 0;
563611e25f0dSDavid C Somayajulu }
563711e25f0dSDavid C Somayajulu 
563811e25f0dSDavid C Somayajulu static int
qlnx_slowpath_start(qlnx_host_t * ha)563911e25f0dSDavid C Somayajulu qlnx_slowpath_start(qlnx_host_t *ha)
564011e25f0dSDavid C Somayajulu {
564111e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
564211e25f0dSDavid C Somayajulu 	struct ecore_pf_params	pf_params;
564311e25f0dSDavid C Somayajulu 	int			rc;
564411e25f0dSDavid C Somayajulu 
564511e25f0dSDavid C Somayajulu 	memset(&pf_params, 0, sizeof(struct ecore_pf_params));
564611e25f0dSDavid C Somayajulu 	pf_params.eth_pf_params.num_cons  =
564711e25f0dSDavid C Somayajulu 		(ha->num_rss) * (ha->num_tc + 1);
564811e25f0dSDavid C Somayajulu 
5649217ec208SDavid C Somayajulu #ifdef QLNX_ENABLE_IWARP
5650217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) != 0) {
5651217ec208SDavid C Somayajulu 		if(ha->personality == ECORE_PCI_ETH_IWARP) {
5652217ec208SDavid C Somayajulu 			device_printf(ha->pci_dev, "setting parameters required by iWARP dev\n");
5653217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.num_qps = 1024;
5654217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.num_srqs = 1024;
5655217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.gl_pi = ECORE_ROCE_PROTOCOL_INDEX;
5656217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.rdma_protocol = ECORE_RDMA_PROTOCOL_IWARP;
5657217ec208SDavid C Somayajulu 		} else if(ha->personality == ECORE_PCI_ETH_ROCE) {
5658217ec208SDavid C Somayajulu 			device_printf(ha->pci_dev, "setting parameters required by RoCE dev\n");
5659217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.num_qps = 8192;
5660217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.num_srqs = 8192;
5661217ec208SDavid C Somayajulu 			//pf_params.rdma_pf_params.min_dpis = 0;
5662217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.min_dpis = 8;
5663217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.roce_edpm_mode = 0;
5664217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.gl_pi = ECORE_ROCE_PROTOCOL_INDEX;
5665217ec208SDavid C Somayajulu 			pf_params.rdma_pf_params.rdma_protocol = ECORE_RDMA_PROTOCOL_ROCE;
5666217ec208SDavid C Somayajulu 		}
5667217ec208SDavid C Somayajulu 	}
5668217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_ENABLE_IWARP */
5669217ec208SDavid C Somayajulu 
567011e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
567111e25f0dSDavid C Somayajulu 
567211e25f0dSDavid C Somayajulu 	rc = qlnx_nic_setup(cdev, &pf_params);
567311e25f0dSDavid C Somayajulu         if (rc)
567411e25f0dSDavid C Somayajulu                 goto qlnx_slowpath_start_exit;
567511e25f0dSDavid C Somayajulu 
567611e25f0dSDavid C Somayajulu         cdev->int_mode = ECORE_INT_MODE_MSIX;
567711e25f0dSDavid C Somayajulu         cdev->int_coalescing_mode = ECORE_COAL_MODE_ENABLE;
567811e25f0dSDavid C Somayajulu 
567911e25f0dSDavid C Somayajulu #ifdef QLNX_MAX_COALESCE
568011e25f0dSDavid C Somayajulu 	cdev->rx_coalesce_usecs = 255;
568111e25f0dSDavid C Somayajulu 	cdev->tx_coalesce_usecs = 255;
568211e25f0dSDavid C Somayajulu #endif
568311e25f0dSDavid C Somayajulu 
568411e25f0dSDavid C Somayajulu 	rc = qlnx_nic_start(cdev);
568511e25f0dSDavid C Somayajulu 
568611e25f0dSDavid C Somayajulu 	ha->rx_coalesce_usecs = cdev->rx_coalesce_usecs;
568711e25f0dSDavid C Somayajulu 	ha->tx_coalesce_usecs = cdev->tx_coalesce_usecs;
568811e25f0dSDavid C Somayajulu 
5689217ec208SDavid C Somayajulu #ifdef QLNX_USER_LLDP
5690217ec208SDavid C Somayajulu 	(void)qlnx_set_lldp_tlvx(ha, NULL);
5691217ec208SDavid C Somayajulu #endif /* #ifdef QLNX_USER_LLDP */
5692217ec208SDavid C Somayajulu 
569311e25f0dSDavid C Somayajulu qlnx_slowpath_start_exit:
569411e25f0dSDavid C Somayajulu 
569511e25f0dSDavid C Somayajulu 	return (rc);
569611e25f0dSDavid C Somayajulu }
569711e25f0dSDavid C Somayajulu 
569811e25f0dSDavid C Somayajulu static int
qlnx_slowpath_stop(qlnx_host_t * ha)569911e25f0dSDavid C Somayajulu qlnx_slowpath_stop(qlnx_host_t *ha)
570011e25f0dSDavid C Somayajulu {
570111e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
570211e25f0dSDavid C Somayajulu 	device_t		dev = ha->pci_dev;
570311e25f0dSDavid C Somayajulu 	int			i;
570411e25f0dSDavid C Somayajulu 
570511e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
570611e25f0dSDavid C Somayajulu 
570711e25f0dSDavid C Somayajulu 	ecore_hw_stop(cdev);
570811e25f0dSDavid C Somayajulu 
570911e25f0dSDavid C Somayajulu  	for (i = 0; i < ha->cdev.num_hwfns; i++) {
571011e25f0dSDavid C Somayajulu         	if (ha->sp_handle[i])
571111e25f0dSDavid C Somayajulu                 	(void)bus_teardown_intr(dev, ha->sp_irq[i],
571211e25f0dSDavid C Somayajulu 				ha->sp_handle[i]);
571311e25f0dSDavid C Somayajulu 
571411e25f0dSDavid C Somayajulu 		ha->sp_handle[i] = NULL;
571511e25f0dSDavid C Somayajulu 
571611e25f0dSDavid C Somayajulu         	if (ha->sp_irq[i])
571711e25f0dSDavid C Somayajulu 			(void) bus_release_resource(dev, SYS_RES_IRQ,
571811e25f0dSDavid C Somayajulu 				ha->sp_irq_rid[i], ha->sp_irq[i]);
571911e25f0dSDavid C Somayajulu 		ha->sp_irq[i] = NULL;
572011e25f0dSDavid C Somayajulu 	}
572111e25f0dSDavid C Somayajulu 
572211e25f0dSDavid C Somayajulu         ecore_resc_free(cdev);
572311e25f0dSDavid C Somayajulu 
572411e25f0dSDavid C Somayajulu         return 0;
572511e25f0dSDavid C Somayajulu }
572611e25f0dSDavid C Somayajulu 
572711e25f0dSDavid C Somayajulu static void
qlnx_set_id(struct ecore_dev * cdev,char name[NAME_SIZE],char ver_str[VER_SIZE])572811e25f0dSDavid C Somayajulu qlnx_set_id(struct ecore_dev *cdev, char name[NAME_SIZE],
572911e25f0dSDavid C Somayajulu 	char ver_str[VER_SIZE])
573011e25f0dSDavid C Somayajulu {
573111e25f0dSDavid C Somayajulu         int	i;
573211e25f0dSDavid C Somayajulu 
573311e25f0dSDavid C Somayajulu         memcpy(cdev->name, name, NAME_SIZE);
573411e25f0dSDavid C Somayajulu 
573511e25f0dSDavid C Somayajulu         for_each_hwfn(cdev, i) {
573611e25f0dSDavid C Somayajulu                 snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i);
573711e25f0dSDavid C Somayajulu         }
573811e25f0dSDavid C Somayajulu 
573911e25f0dSDavid C Somayajulu         cdev->drv_type = DRV_ID_DRV_TYPE_FREEBSD;
574011e25f0dSDavid C Somayajulu 
574111e25f0dSDavid C Somayajulu 	return ;
574211e25f0dSDavid C Somayajulu }
574311e25f0dSDavid C Somayajulu 
574411e25f0dSDavid C Somayajulu void
qlnx_get_protocol_stats(void * cdev,int proto_type,void * proto_stats)574511e25f0dSDavid C Somayajulu qlnx_get_protocol_stats(void *cdev, int proto_type, void *proto_stats)
574611e25f0dSDavid C Somayajulu {
574711e25f0dSDavid C Somayajulu 	enum ecore_mcp_protocol_type	type;
574811e25f0dSDavid C Somayajulu 	union ecore_mcp_protocol_stats	*stats;
574911e25f0dSDavid C Somayajulu 	struct ecore_eth_stats		eth_stats;
57507a377fbeSDavid C Somayajulu 	qlnx_host_t			*ha;
575111e25f0dSDavid C Somayajulu 
57527a377fbeSDavid C Somayajulu 	ha = cdev;
575311e25f0dSDavid C Somayajulu 	stats = proto_stats;
575411e25f0dSDavid C Somayajulu 	type = proto_type;
575511e25f0dSDavid C Somayajulu 
575611e25f0dSDavid C Somayajulu         switch (type) {
575711e25f0dSDavid C Somayajulu         case ECORE_MCP_LAN_STATS:
575811e25f0dSDavid C Somayajulu                 ecore_get_vport_stats((struct ecore_dev *)cdev, &eth_stats);
575911e25f0dSDavid C Somayajulu                 stats->lan_stats.ucast_rx_pkts = eth_stats.common.rx_ucast_pkts;
576011e25f0dSDavid C Somayajulu                 stats->lan_stats.ucast_tx_pkts = eth_stats.common.tx_ucast_pkts;
576111e25f0dSDavid C Somayajulu                 stats->lan_stats.fcs_err = -1;
576211e25f0dSDavid C Somayajulu                 break;
576311e25f0dSDavid C Somayajulu 
576411e25f0dSDavid C Somayajulu 	default:
57657a377fbeSDavid C Somayajulu 		ha->err_get_proto_invalid_type++;
576611e25f0dSDavid C Somayajulu 
57677a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "invalid protocol type 0x%x\n", type);
576811e25f0dSDavid C Somayajulu 		break;
576911e25f0dSDavid C Somayajulu 	}
577011e25f0dSDavid C Somayajulu 	return;
577111e25f0dSDavid C Somayajulu }
577211e25f0dSDavid C Somayajulu 
577311e25f0dSDavid C Somayajulu static int
qlnx_get_mfw_version(qlnx_host_t * ha,uint32_t * mfw_ver)577411e25f0dSDavid C Somayajulu qlnx_get_mfw_version(qlnx_host_t *ha, uint32_t *mfw_ver)
577511e25f0dSDavid C Somayajulu {
577611e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
577711e25f0dSDavid C Somayajulu 	struct ecore_ptt	*p_ptt;
577811e25f0dSDavid C Somayajulu 
577911e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
578011e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
578111e25f0dSDavid C Somayajulu 
578211e25f0dSDavid C Somayajulu 	if (p_ptt ==  NULL) {
57837a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_ptt_acquire failed\n");
578411e25f0dSDavid C Somayajulu                 return (-1);
578511e25f0dSDavid C Somayajulu 	}
578611e25f0dSDavid C Somayajulu 	ecore_mcp_get_mfw_ver(p_hwfn, p_ptt, mfw_ver, NULL);
578711e25f0dSDavid C Somayajulu 
578811e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
578911e25f0dSDavid C Somayajulu 
579011e25f0dSDavid C Somayajulu 	return (0);
579111e25f0dSDavid C Somayajulu }
579211e25f0dSDavid C Somayajulu 
579311e25f0dSDavid C Somayajulu static int
qlnx_get_flash_size(qlnx_host_t * ha,uint32_t * flash_size)579411e25f0dSDavid C Somayajulu qlnx_get_flash_size(qlnx_host_t *ha, uint32_t *flash_size)
579511e25f0dSDavid C Somayajulu {
579611e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
579711e25f0dSDavid C Somayajulu 	struct ecore_ptt	*p_ptt;
579811e25f0dSDavid C Somayajulu 
579911e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[0];
580011e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
580111e25f0dSDavid C Somayajulu 
580211e25f0dSDavid C Somayajulu 	if (p_ptt ==  NULL) {
58037a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha,"ecore_ptt_acquire failed\n");
580411e25f0dSDavid C Somayajulu                 return (-1);
580511e25f0dSDavid C Somayajulu 	}
580611e25f0dSDavid C Somayajulu 	ecore_mcp_get_flash_size(p_hwfn, p_ptt, flash_size);
580711e25f0dSDavid C Somayajulu 
580811e25f0dSDavid C Somayajulu 	ecore_ptt_release(p_hwfn, p_ptt);
580911e25f0dSDavid C Somayajulu 
581011e25f0dSDavid C Somayajulu 	return (0);
581111e25f0dSDavid C Somayajulu }
581211e25f0dSDavid C Somayajulu 
581311e25f0dSDavid C Somayajulu static int
qlnx_alloc_mem_arrays(qlnx_host_t * ha)581411e25f0dSDavid C Somayajulu qlnx_alloc_mem_arrays(qlnx_host_t *ha)
581511e25f0dSDavid C Somayajulu {
581611e25f0dSDavid C Somayajulu 	bzero(&ha->txq_array[0], (sizeof(struct qlnx_tx_queue) * QLNX_MAX_RSS));
581711e25f0dSDavid C Somayajulu 	bzero(&ha->rxq_array[0], (sizeof(struct qlnx_rx_queue) * QLNX_MAX_RSS));
581811e25f0dSDavid C Somayajulu 	bzero(&ha->sb_array[0], (sizeof(struct ecore_sb_info) * QLNX_MAX_RSS));
581911e25f0dSDavid C Somayajulu 
582011e25f0dSDavid C Somayajulu         return 0;
582111e25f0dSDavid C Somayajulu }
582211e25f0dSDavid C Somayajulu 
582311e25f0dSDavid C Somayajulu static void
qlnx_init_fp(qlnx_host_t * ha)582411e25f0dSDavid C Somayajulu qlnx_init_fp(qlnx_host_t *ha)
582511e25f0dSDavid C Somayajulu {
582611e25f0dSDavid C Somayajulu 	int rss_id, txq_array_index, tc;
582711e25f0dSDavid C Somayajulu 
582811e25f0dSDavid C Somayajulu 	for (rss_id = 0; rss_id < ha->num_rss; rss_id++) {
582911e25f0dSDavid C Somayajulu 		struct qlnx_fastpath *fp = &ha->fp_array[rss_id];
583011e25f0dSDavid C Somayajulu 
583111e25f0dSDavid C Somayajulu 		fp->rss_id = rss_id;
583211e25f0dSDavid C Somayajulu 		fp->edev = ha;
583311e25f0dSDavid C Somayajulu 		fp->sb_info = &ha->sb_array[rss_id];
583411e25f0dSDavid C Somayajulu 		fp->rxq = &ha->rxq_array[rss_id];
583511e25f0dSDavid C Somayajulu 		fp->rxq->rxq_id = rss_id;
583611e25f0dSDavid C Somayajulu 
583711e25f0dSDavid C Somayajulu 		for (tc = 0; tc < ha->num_tc; tc++) {
583811e25f0dSDavid C Somayajulu                         txq_array_index = tc * ha->num_rss + rss_id;
583911e25f0dSDavid C Somayajulu                         fp->txq[tc] = &ha->txq_array[txq_array_index];
584011e25f0dSDavid C Somayajulu                         fp->txq[tc]->index = txq_array_index;
584111e25f0dSDavid C Somayajulu 		}
584211e25f0dSDavid C Somayajulu 
584311e25f0dSDavid C Somayajulu 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", qlnx_name_str,
584411e25f0dSDavid C Somayajulu 			rss_id);
584511e25f0dSDavid C Somayajulu 
584677388ed2SDavid C Somayajulu 		fp->tx_ring_full = 0;
584777388ed2SDavid C Somayajulu 
584811e25f0dSDavid C Somayajulu 		/* reset all the statistics counters */
584911e25f0dSDavid C Somayajulu 
585011e25f0dSDavid C Somayajulu 		fp->tx_pkts_processed = 0;
585111e25f0dSDavid C Somayajulu 		fp->tx_pkts_freed = 0;
585211e25f0dSDavid C Somayajulu 		fp->tx_pkts_transmitted = 0;
585311e25f0dSDavid C Somayajulu 		fp->tx_pkts_completed = 0;
585445f13123SDavid C Somayajulu 
585545f13123SDavid C Somayajulu #ifdef QLNX_TRACE_PERF_DATA
585645f13123SDavid C Somayajulu 		fp->tx_pkts_trans_ctx = 0;
585745f13123SDavid C Somayajulu 		fp->tx_pkts_compl_ctx = 0;
585845f13123SDavid C Somayajulu 		fp->tx_pkts_trans_fp = 0;
585945f13123SDavid C Somayajulu 		fp->tx_pkts_compl_fp = 0;
586045f13123SDavid C Somayajulu 		fp->tx_pkts_compl_intr = 0;
586145f13123SDavid C Somayajulu #endif
586211e25f0dSDavid C Somayajulu 		fp->tx_lso_wnd_min_len = 0;
586311e25f0dSDavid C Somayajulu 		fp->tx_defrag = 0;
586411e25f0dSDavid C Somayajulu 		fp->tx_nsegs_gt_elem_left = 0;
586511e25f0dSDavid C Somayajulu 		fp->tx_tso_max_nsegs = 0;
586611e25f0dSDavid C Somayajulu 		fp->tx_tso_min_nsegs = 0;
586711e25f0dSDavid C Somayajulu 		fp->err_tx_nsegs_gt_elem_left = 0;
586811e25f0dSDavid C Somayajulu 		fp->err_tx_dmamap_create = 0;
586911e25f0dSDavid C Somayajulu 		fp->err_tx_defrag_dmamap_load = 0;
587011e25f0dSDavid C Somayajulu 		fp->err_tx_non_tso_max_seg = 0;
587111e25f0dSDavid C Somayajulu 		fp->err_tx_dmamap_load = 0;
587211e25f0dSDavid C Somayajulu 		fp->err_tx_defrag = 0;
587311e25f0dSDavid C Somayajulu 		fp->err_tx_free_pkt_null = 0;
587411e25f0dSDavid C Somayajulu 		fp->err_tx_cons_idx_conflict = 0;
587511e25f0dSDavid C Somayajulu 
587611e25f0dSDavid C Somayajulu 		fp->rx_pkts = 0;
587711e25f0dSDavid C Somayajulu 		fp->err_m_getcl = 0;
587811e25f0dSDavid C Somayajulu 		fp->err_m_getjcl = 0;
587911e25f0dSDavid C Somayajulu         }
588011e25f0dSDavid C Somayajulu 	return;
588111e25f0dSDavid C Somayajulu }
588211e25f0dSDavid C Somayajulu 
5883217ec208SDavid C Somayajulu void
qlnx_free_mem_sb(qlnx_host_t * ha,struct ecore_sb_info * sb_info)588411e25f0dSDavid C Somayajulu qlnx_free_mem_sb(qlnx_host_t *ha, struct ecore_sb_info *sb_info)
588511e25f0dSDavid C Somayajulu {
588611e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
588711e25f0dSDavid C Somayajulu 
588811e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
588911e25f0dSDavid C Somayajulu 
589011e25f0dSDavid C Somayajulu         if (sb_info->sb_virt) {
589111e25f0dSDavid C Somayajulu                 OSAL_DMA_FREE_COHERENT(cdev, ((void *)sb_info->sb_virt),
589211e25f0dSDavid C Somayajulu 			(sb_info->sb_phys), (sizeof(*sb_info->sb_virt)));
589311e25f0dSDavid C Somayajulu 		sb_info->sb_virt = NULL;
589411e25f0dSDavid C Somayajulu 	}
589511e25f0dSDavid C Somayajulu }
589611e25f0dSDavid C Somayajulu 
589711e25f0dSDavid C Somayajulu static int
qlnx_sb_init(struct ecore_dev * cdev,struct ecore_sb_info * sb_info,void * sb_virt_addr,bus_addr_t sb_phy_addr,u16 sb_id)589811e25f0dSDavid C Somayajulu qlnx_sb_init(struct ecore_dev *cdev, struct ecore_sb_info *sb_info,
589911e25f0dSDavid C Somayajulu 	void *sb_virt_addr, bus_addr_t sb_phy_addr, u16 sb_id)
590011e25f0dSDavid C Somayajulu {
590111e25f0dSDavid C Somayajulu         struct ecore_hwfn	*p_hwfn;
590211e25f0dSDavid C Somayajulu         int			hwfn_index, rc;
590311e25f0dSDavid C Somayajulu         u16			rel_sb_id;
590411e25f0dSDavid C Somayajulu 
590511e25f0dSDavid C Somayajulu         hwfn_index = sb_id % cdev->num_hwfns;
590611e25f0dSDavid C Somayajulu         p_hwfn = &cdev->hwfns[hwfn_index];
590711e25f0dSDavid C Somayajulu         rel_sb_id = sb_id / cdev->num_hwfns;
590811e25f0dSDavid C Somayajulu 
59097a377fbeSDavid C Somayajulu         QL_DPRINT2(((qlnx_host_t *)cdev),
59107a377fbeSDavid C Somayajulu                 "hwfn_index = %d p_hwfn = %p sb_id = 0x%x rel_sb_id = 0x%x \
59117a377fbeSDavid C Somayajulu                 sb_info = %p sb_virt_addr = %p sb_phy_addr = %p\n",
59127a377fbeSDavid C Somayajulu                 hwfn_index, p_hwfn, sb_id, rel_sb_id, sb_info,
59137a377fbeSDavid C Somayajulu                 sb_virt_addr, (void *)sb_phy_addr);
591411e25f0dSDavid C Somayajulu 
591511e25f0dSDavid C Somayajulu         rc = ecore_int_sb_init(p_hwfn, p_hwfn->p_main_ptt, sb_info,
591611e25f0dSDavid C Somayajulu                              sb_virt_addr, sb_phy_addr, rel_sb_id);
591711e25f0dSDavid C Somayajulu 
591811e25f0dSDavid C Somayajulu         return rc;
591911e25f0dSDavid C Somayajulu }
592011e25f0dSDavid C Somayajulu 
592111e25f0dSDavid C Somayajulu /* This function allocates fast-path status block memory */
5922217ec208SDavid C Somayajulu int
qlnx_alloc_mem_sb(qlnx_host_t * ha,struct ecore_sb_info * sb_info,u16 sb_id)592311e25f0dSDavid C Somayajulu qlnx_alloc_mem_sb(qlnx_host_t *ha, struct ecore_sb_info *sb_info, u16 sb_id)
592411e25f0dSDavid C Somayajulu {
59259efd0ba7SDavid C Somayajulu         struct status_block_e4	*sb_virt;
592611e25f0dSDavid C Somayajulu         bus_addr_t		sb_phys;
592711e25f0dSDavid C Somayajulu         int			rc;
592811e25f0dSDavid C Somayajulu 	uint32_t		size;
592911e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
593011e25f0dSDavid C Somayajulu 
593111e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
593211e25f0dSDavid C Somayajulu 
593311e25f0dSDavid C Somayajulu 	size = sizeof(*sb_virt);
593411e25f0dSDavid C Somayajulu 	sb_virt = OSAL_DMA_ALLOC_COHERENT(cdev, (&sb_phys), size);
593511e25f0dSDavid C Somayajulu 
593611e25f0dSDavid C Somayajulu         if (!sb_virt) {
59377a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "Status block allocation failed\n");
593811e25f0dSDavid C Somayajulu                 return -ENOMEM;
593911e25f0dSDavid C Somayajulu         }
594011e25f0dSDavid C Somayajulu 
594111e25f0dSDavid C Somayajulu         rc = qlnx_sb_init(cdev, sb_info, sb_virt, sb_phys, sb_id);
594211e25f0dSDavid C Somayajulu         if (rc) {
594311e25f0dSDavid C Somayajulu                 OSAL_DMA_FREE_COHERENT(cdev, sb_virt, sb_phys, size);
594411e25f0dSDavid C Somayajulu         }
594511e25f0dSDavid C Somayajulu 
594611e25f0dSDavid C Somayajulu 	return rc;
594711e25f0dSDavid C Somayajulu }
594811e25f0dSDavid C Somayajulu 
594911e25f0dSDavid C Somayajulu static void
qlnx_free_rx_buffers(qlnx_host_t * ha,struct qlnx_rx_queue * rxq)595011e25f0dSDavid C Somayajulu qlnx_free_rx_buffers(qlnx_host_t *ha, struct qlnx_rx_queue *rxq)
595111e25f0dSDavid C Somayajulu {
595211e25f0dSDavid C Somayajulu         int			i;
595311e25f0dSDavid C Somayajulu 	struct sw_rx_data	*rx_buf;
595411e25f0dSDavid C Somayajulu 
595511e25f0dSDavid C Somayajulu         for (i = 0; i < rxq->num_rx_buffers; i++) {
595611e25f0dSDavid C Somayajulu                 rx_buf = &rxq->sw_rx_ring[i];
595711e25f0dSDavid C Somayajulu 
595811e25f0dSDavid C Somayajulu 		if (rx_buf->data != NULL) {
595911e25f0dSDavid C Somayajulu 			if (rx_buf->map != NULL) {
596011e25f0dSDavid C Somayajulu 				bus_dmamap_unload(ha->rx_tag, rx_buf->map);
596111e25f0dSDavid C Somayajulu 				bus_dmamap_destroy(ha->rx_tag, rx_buf->map);
596211e25f0dSDavid C Somayajulu 				rx_buf->map = NULL;
596311e25f0dSDavid C Somayajulu 			}
596411e25f0dSDavid C Somayajulu 			m_freem(rx_buf->data);
596511e25f0dSDavid C Somayajulu 			rx_buf->data = NULL;
596611e25f0dSDavid C Somayajulu 		}
596711e25f0dSDavid C Somayajulu         }
596811e25f0dSDavid C Somayajulu 	return;
596911e25f0dSDavid C Somayajulu }
597011e25f0dSDavid C Somayajulu 
597111e25f0dSDavid C Somayajulu static void
qlnx_free_mem_rxq(qlnx_host_t * ha,struct qlnx_rx_queue * rxq)597211e25f0dSDavid C Somayajulu qlnx_free_mem_rxq(qlnx_host_t *ha, struct qlnx_rx_queue *rxq)
597311e25f0dSDavid C Somayajulu {
597411e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
597511e25f0dSDavid C Somayajulu 	int			i;
597611e25f0dSDavid C Somayajulu 
597711e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
597811e25f0dSDavid C Somayajulu 
597911e25f0dSDavid C Somayajulu 	qlnx_free_rx_buffers(ha, rxq);
598011e25f0dSDavid C Somayajulu 
598111e25f0dSDavid C Somayajulu 	for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) {
598211e25f0dSDavid C Somayajulu 		qlnx_free_tpa_mbuf(ha, &rxq->tpa_info[i]);
598311e25f0dSDavid C Somayajulu 		if (rxq->tpa_info[i].mpf != NULL)
598411e25f0dSDavid C Somayajulu 			m_freem(rxq->tpa_info[i].mpf);
598511e25f0dSDavid C Somayajulu 	}
598611e25f0dSDavid C Somayajulu 
598711e25f0dSDavid C Somayajulu 	bzero((void *)&rxq->sw_rx_ring[0],
598811e25f0dSDavid C Somayajulu 		(sizeof (struct sw_rx_data) * RX_RING_SIZE));
598911e25f0dSDavid C Somayajulu 
599011e25f0dSDavid C Somayajulu         /* Free the real RQ ring used by FW */
599111e25f0dSDavid C Somayajulu 	if (rxq->rx_bd_ring.p_virt_addr) {
599211e25f0dSDavid C Somayajulu                 ecore_chain_free(cdev, &rxq->rx_bd_ring);
599311e25f0dSDavid C Somayajulu                 rxq->rx_bd_ring.p_virt_addr = NULL;
599411e25f0dSDavid C Somayajulu         }
599511e25f0dSDavid C Somayajulu 
599611e25f0dSDavid C Somayajulu         /* Free the real completion ring used by FW */
599711e25f0dSDavid C Somayajulu         if (rxq->rx_comp_ring.p_virt_addr &&
599811e25f0dSDavid C Somayajulu                         rxq->rx_comp_ring.pbl_sp.p_virt_table) {
599911e25f0dSDavid C Somayajulu                 ecore_chain_free(cdev, &rxq->rx_comp_ring);
600011e25f0dSDavid C Somayajulu                 rxq->rx_comp_ring.p_virt_addr = NULL;
600111e25f0dSDavid C Somayajulu                 rxq->rx_comp_ring.pbl_sp.p_virt_table = NULL;
600211e25f0dSDavid C Somayajulu         }
600311e25f0dSDavid C Somayajulu 
600411e25f0dSDavid C Somayajulu #ifdef QLNX_SOFT_LRO
600511e25f0dSDavid C Somayajulu 	{
600611e25f0dSDavid C Somayajulu 		struct lro_ctrl *lro;
600711e25f0dSDavid C Somayajulu 
600811e25f0dSDavid C Somayajulu 		lro = &rxq->lro;
600911e25f0dSDavid C Somayajulu 		tcp_lro_free(lro);
601011e25f0dSDavid C Somayajulu 	}
601111e25f0dSDavid C Somayajulu #endif /* #ifdef QLNX_SOFT_LRO */
601211e25f0dSDavid C Somayajulu 
601311e25f0dSDavid C Somayajulu 	return;
601411e25f0dSDavid C Somayajulu }
601511e25f0dSDavid C Somayajulu 
601611e25f0dSDavid C Somayajulu static int
qlnx_alloc_rx_buffer(qlnx_host_t * ha,struct qlnx_rx_queue * rxq)601711e25f0dSDavid C Somayajulu qlnx_alloc_rx_buffer(qlnx_host_t *ha, struct qlnx_rx_queue *rxq)
601811e25f0dSDavid C Somayajulu {
601911e25f0dSDavid C Somayajulu         register struct mbuf	*mp;
602011e25f0dSDavid C Somayajulu         uint16_t		rx_buf_size;
602111e25f0dSDavid C Somayajulu         struct sw_rx_data	*sw_rx_data;
602211e25f0dSDavid C Somayajulu         struct eth_rx_bd	*rx_bd;
602311e25f0dSDavid C Somayajulu         dma_addr_t		dma_addr;
602411e25f0dSDavid C Somayajulu 	bus_dmamap_t		map;
602511e25f0dSDavid C Somayajulu 	bus_dma_segment_t       segs[1];
602611e25f0dSDavid C Somayajulu 	int			nsegs;
602711e25f0dSDavid C Somayajulu 	int			ret;
602811e25f0dSDavid C Somayajulu 
602911e25f0dSDavid C Somayajulu         rx_buf_size = rxq->rx_buf_size;
603011e25f0dSDavid C Somayajulu 
603111e25f0dSDavid C Somayajulu 	mp = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, rx_buf_size);
603211e25f0dSDavid C Somayajulu 
603311e25f0dSDavid C Somayajulu         if (mp == NULL) {
60347a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "Failed to allocate Rx data\n");
603511e25f0dSDavid C Somayajulu                 return -ENOMEM;
603611e25f0dSDavid C Somayajulu         }
603711e25f0dSDavid C Somayajulu 
603811e25f0dSDavid C Somayajulu 	mp->m_len = mp->m_pkthdr.len = rx_buf_size;
603911e25f0dSDavid C Somayajulu 
604011e25f0dSDavid C Somayajulu 	map = (bus_dmamap_t)0;
604111e25f0dSDavid C Somayajulu 
604211e25f0dSDavid C Somayajulu 	ret = bus_dmamap_load_mbuf_sg(ha->rx_tag, map, mp, segs, &nsegs,
604311e25f0dSDavid C Somayajulu 			BUS_DMA_NOWAIT);
604411e25f0dSDavid C Somayajulu 	dma_addr = segs[0].ds_addr;
604511e25f0dSDavid C Somayajulu 
604611e25f0dSDavid C Somayajulu 	if (ret || !dma_addr || (nsegs != 1)) {
604711e25f0dSDavid C Somayajulu 		m_freem(mp);
60487a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "bus_dmamap_load failed[%d, 0x%016llx, %d]\n",
60497a377fbeSDavid C Somayajulu                            ret, (long long unsigned int)dma_addr, nsegs);
605011e25f0dSDavid C Somayajulu 		return -ENOMEM;
605111e25f0dSDavid C Somayajulu 	}
605211e25f0dSDavid C Somayajulu 
605311e25f0dSDavid C Somayajulu         sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_prod];
605411e25f0dSDavid C Somayajulu         sw_rx_data->data = mp;
605511e25f0dSDavid C Somayajulu         sw_rx_data->dma_addr = dma_addr;
605611e25f0dSDavid C Somayajulu         sw_rx_data->map = map;
605711e25f0dSDavid C Somayajulu 
605811e25f0dSDavid C Somayajulu         /* Advance PROD and get BD pointer */
605911e25f0dSDavid C Somayajulu         rx_bd = (struct eth_rx_bd *)ecore_chain_produce(&rxq->rx_bd_ring);
606011e25f0dSDavid C Somayajulu         rx_bd->addr.hi = htole32(U64_HI(dma_addr));
606111e25f0dSDavid C Somayajulu         rx_bd->addr.lo = htole32(U64_LO(dma_addr));
606211e25f0dSDavid C Somayajulu 	bus_dmamap_sync(ha->rx_tag, map, BUS_DMASYNC_PREREAD);
606311e25f0dSDavid C Somayajulu 
606411e25f0dSDavid C Somayajulu         rxq->sw_rx_prod = (rxq->sw_rx_prod + 1) & (RX_RING_SIZE - 1);
606511e25f0dSDavid C Somayajulu 
606611e25f0dSDavid C Somayajulu         return 0;
606711e25f0dSDavid C Somayajulu }
606811e25f0dSDavid C Somayajulu 
606911e25f0dSDavid C Somayajulu static int
qlnx_alloc_tpa_mbuf(qlnx_host_t * ha,uint16_t rx_buf_size,struct qlnx_agg_info * tpa)607011e25f0dSDavid C Somayajulu qlnx_alloc_tpa_mbuf(qlnx_host_t *ha, uint16_t rx_buf_size,
607111e25f0dSDavid C Somayajulu 	struct qlnx_agg_info *tpa)
607211e25f0dSDavid C Somayajulu {
607311e25f0dSDavid C Somayajulu 	struct mbuf		*mp;
607411e25f0dSDavid C Somayajulu         dma_addr_t		dma_addr;
607511e25f0dSDavid C Somayajulu 	bus_dmamap_t		map;
607611e25f0dSDavid C Somayajulu 	bus_dma_segment_t       segs[1];
607711e25f0dSDavid C Somayajulu 	int			nsegs;
607811e25f0dSDavid C Somayajulu 	int			ret;
607911e25f0dSDavid C Somayajulu         struct sw_rx_data	*rx_buf;
608011e25f0dSDavid C Somayajulu 
608111e25f0dSDavid C Somayajulu 	mp = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, rx_buf_size);
608211e25f0dSDavid C Somayajulu 
608311e25f0dSDavid C Somayajulu         if (mp == NULL) {
60847a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "Failed to allocate Rx data\n");
608511e25f0dSDavid C Somayajulu                 return -ENOMEM;
608611e25f0dSDavid C Somayajulu         }
608711e25f0dSDavid C Somayajulu 
608811e25f0dSDavid C Somayajulu 	mp->m_len = mp->m_pkthdr.len = rx_buf_size;
608911e25f0dSDavid C Somayajulu 
609011e25f0dSDavid C Somayajulu 	map = (bus_dmamap_t)0;
609111e25f0dSDavid C Somayajulu 
609211e25f0dSDavid C Somayajulu 	ret = bus_dmamap_load_mbuf_sg(ha->rx_tag, map, mp, segs, &nsegs,
609311e25f0dSDavid C Somayajulu 			BUS_DMA_NOWAIT);
609411e25f0dSDavid C Somayajulu 	dma_addr = segs[0].ds_addr;
609511e25f0dSDavid C Somayajulu 
609611e25f0dSDavid C Somayajulu 	if (ret || !dma_addr || (nsegs != 1)) {
609711e25f0dSDavid C Somayajulu 		m_freem(mp);
60987a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "bus_dmamap_load failed[%d, 0x%016llx, %d]\n",
60997a377fbeSDavid C Somayajulu 			ret, (long long unsigned int)dma_addr, nsegs);
610011e25f0dSDavid C Somayajulu 		return -ENOMEM;
610111e25f0dSDavid C Somayajulu 	}
610211e25f0dSDavid C Somayajulu 
610311e25f0dSDavid C Somayajulu         rx_buf = &tpa->rx_buf;
610411e25f0dSDavid C Somayajulu 
610511e25f0dSDavid C Somayajulu 	memset(rx_buf, 0, sizeof (struct sw_rx_data));
610611e25f0dSDavid C Somayajulu 
610711e25f0dSDavid C Somayajulu         rx_buf->data = mp;
610811e25f0dSDavid C Somayajulu         rx_buf->dma_addr = dma_addr;
610911e25f0dSDavid C Somayajulu         rx_buf->map = map;
611011e25f0dSDavid C Somayajulu 
611111e25f0dSDavid C Somayajulu 	bus_dmamap_sync(ha->rx_tag, map, BUS_DMASYNC_PREREAD);
611211e25f0dSDavid C Somayajulu 
611311e25f0dSDavid C Somayajulu 	return (0);
611411e25f0dSDavid C Somayajulu }
611511e25f0dSDavid C Somayajulu 
611611e25f0dSDavid C Somayajulu static void
qlnx_free_tpa_mbuf(qlnx_host_t * ha,struct qlnx_agg_info * tpa)611711e25f0dSDavid C Somayajulu qlnx_free_tpa_mbuf(qlnx_host_t *ha, struct qlnx_agg_info *tpa)
611811e25f0dSDavid C Somayajulu {
611911e25f0dSDavid C Somayajulu         struct sw_rx_data	*rx_buf;
612011e25f0dSDavid C Somayajulu 
612111e25f0dSDavid C Somayajulu 	rx_buf = &tpa->rx_buf;
612211e25f0dSDavid C Somayajulu 
612311e25f0dSDavid C Somayajulu 	if (rx_buf->data != NULL) {
612411e25f0dSDavid C Somayajulu 		if (rx_buf->map != NULL) {
612511e25f0dSDavid C Somayajulu 			bus_dmamap_unload(ha->rx_tag, rx_buf->map);
612611e25f0dSDavid C Somayajulu 			bus_dmamap_destroy(ha->rx_tag, rx_buf->map);
612711e25f0dSDavid C Somayajulu 			rx_buf->map = NULL;
612811e25f0dSDavid C Somayajulu 		}
612911e25f0dSDavid C Somayajulu 		m_freem(rx_buf->data);
613011e25f0dSDavid C Somayajulu 		rx_buf->data = NULL;
613111e25f0dSDavid C Somayajulu 	}
613211e25f0dSDavid C Somayajulu 	return;
613311e25f0dSDavid C Somayajulu }
613411e25f0dSDavid C Somayajulu 
613511e25f0dSDavid C Somayajulu /* This function allocates all memory needed per Rx queue */
613611e25f0dSDavid C Somayajulu static int
qlnx_alloc_mem_rxq(qlnx_host_t * ha,struct qlnx_rx_queue * rxq)613711e25f0dSDavid C Somayajulu qlnx_alloc_mem_rxq(qlnx_host_t *ha, struct qlnx_rx_queue *rxq)
613811e25f0dSDavid C Somayajulu {
613911e25f0dSDavid C Somayajulu         int			i, rc, num_allocated;
614011e25f0dSDavid C Somayajulu 	struct ecore_dev	 *cdev;
614111e25f0dSDavid C Somayajulu 
614211e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
614311e25f0dSDavid C Somayajulu 
614411e25f0dSDavid C Somayajulu         rxq->num_rx_buffers = RX_RING_SIZE;
614511e25f0dSDavid C Somayajulu 
614611e25f0dSDavid C Somayajulu 	rxq->rx_buf_size = ha->rx_buf_size;
614711e25f0dSDavid C Somayajulu 
614811e25f0dSDavid C Somayajulu         /* Allocate the parallel driver ring for Rx buffers */
614911e25f0dSDavid C Somayajulu 	bzero((void *)&rxq->sw_rx_ring[0],
615011e25f0dSDavid C Somayajulu 		(sizeof (struct sw_rx_data) * RX_RING_SIZE));
615111e25f0dSDavid C Somayajulu 
615211e25f0dSDavid C Somayajulu         /* Allocate FW Rx ring  */
615311e25f0dSDavid C Somayajulu 
615411e25f0dSDavid C Somayajulu         rc = ecore_chain_alloc(cdev,
615511e25f0dSDavid C Somayajulu 			ECORE_CHAIN_USE_TO_CONSUME_PRODUCE,
615611e25f0dSDavid C Somayajulu 			ECORE_CHAIN_MODE_NEXT_PTR,
615711e25f0dSDavid C Somayajulu 			ECORE_CHAIN_CNT_TYPE_U16,
615811e25f0dSDavid C Somayajulu 			RX_RING_SIZE,
615911e25f0dSDavid C Somayajulu 			sizeof(struct eth_rx_bd),
616011e25f0dSDavid C Somayajulu 			&rxq->rx_bd_ring, NULL);
616111e25f0dSDavid C Somayajulu 
616211e25f0dSDavid C Somayajulu         if (rc)
616311e25f0dSDavid C Somayajulu                 goto err;
616411e25f0dSDavid C Somayajulu 
616511e25f0dSDavid C Somayajulu         /* Allocate FW completion ring */
616611e25f0dSDavid C Somayajulu         rc = ecore_chain_alloc(cdev,
616711e25f0dSDavid C Somayajulu                         ECORE_CHAIN_USE_TO_CONSUME,
616811e25f0dSDavid C Somayajulu                         ECORE_CHAIN_MODE_PBL,
616911e25f0dSDavid C Somayajulu 			ECORE_CHAIN_CNT_TYPE_U16,
617011e25f0dSDavid C Somayajulu                         RX_RING_SIZE,
617111e25f0dSDavid C Somayajulu                         sizeof(union eth_rx_cqe),
617211e25f0dSDavid C Somayajulu                         &rxq->rx_comp_ring, NULL);
617311e25f0dSDavid C Somayajulu 
617411e25f0dSDavid C Somayajulu         if (rc)
617511e25f0dSDavid C Somayajulu                 goto err;
617611e25f0dSDavid C Somayajulu 
617711e25f0dSDavid C Somayajulu         /* Allocate buffers for the Rx ring */
617811e25f0dSDavid C Somayajulu 
617911e25f0dSDavid C Somayajulu 	for (i = 0; i < ETH_TPA_MAX_AGGS_NUM; i++) {
618011e25f0dSDavid C Somayajulu 		rc = qlnx_alloc_tpa_mbuf(ha, rxq->rx_buf_size,
618111e25f0dSDavid C Somayajulu 			&rxq->tpa_info[i]);
618211e25f0dSDavid C Somayajulu                 if (rc)
618311e25f0dSDavid C Somayajulu                         break;
618411e25f0dSDavid C Somayajulu 	}
618511e25f0dSDavid C Somayajulu 
618611e25f0dSDavid C Somayajulu         for (i = 0; i < rxq->num_rx_buffers; i++) {
618711e25f0dSDavid C Somayajulu                 rc = qlnx_alloc_rx_buffer(ha, rxq);
618811e25f0dSDavid C Somayajulu                 if (rc)
618911e25f0dSDavid C Somayajulu                         break;
619011e25f0dSDavid C Somayajulu         }
619111e25f0dSDavid C Somayajulu         num_allocated = i;
619211e25f0dSDavid C Somayajulu         if (!num_allocated) {
61937a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "Rx buffers allocation failed\n");
619411e25f0dSDavid C Somayajulu                 goto err;
619511e25f0dSDavid C Somayajulu         } else if (num_allocated < rxq->num_rx_buffers) {
61967a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "Allocated less buffers than"
61977a377fbeSDavid C Somayajulu 			" desired (%d allocated)\n", num_allocated);
619811e25f0dSDavid C Somayajulu         }
619911e25f0dSDavid C Somayajulu 
620011e25f0dSDavid C Somayajulu #ifdef QLNX_SOFT_LRO
620111e25f0dSDavid C Somayajulu 
620211e25f0dSDavid C Somayajulu 	{
620311e25f0dSDavid C Somayajulu 		struct lro_ctrl *lro;
620411e25f0dSDavid C Somayajulu 
620511e25f0dSDavid C Somayajulu 		lro = &rxq->lro;
620611e25f0dSDavid C Somayajulu 
620711e25f0dSDavid C Somayajulu 		if (tcp_lro_init_args(lro, ifp, 0, rxq->num_rx_buffers)) {
62087a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "tcp_lro_init[%d] failed\n",
62097a377fbeSDavid C Somayajulu 				   rxq->rxq_id);
621011e25f0dSDavid C Somayajulu 			goto err;
621111e25f0dSDavid C Somayajulu 		}
621211e25f0dSDavid C Somayajulu 
621311e25f0dSDavid C Somayajulu 		lro->ifp = ha->ifp;
621411e25f0dSDavid C Somayajulu 	}
621511e25f0dSDavid C Somayajulu #endif /* #ifdef QLNX_SOFT_LRO */
621611e25f0dSDavid C Somayajulu         return 0;
621711e25f0dSDavid C Somayajulu 
621811e25f0dSDavid C Somayajulu err:
621911e25f0dSDavid C Somayajulu         qlnx_free_mem_rxq(ha, rxq);
622011e25f0dSDavid C Somayajulu         return -ENOMEM;
622111e25f0dSDavid C Somayajulu }
622211e25f0dSDavid C Somayajulu 
622311e25f0dSDavid C Somayajulu static void
qlnx_free_mem_txq(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_tx_queue * txq)622411e25f0dSDavid C Somayajulu qlnx_free_mem_txq(qlnx_host_t *ha, struct qlnx_fastpath *fp,
622511e25f0dSDavid C Somayajulu 	struct qlnx_tx_queue *txq)
622611e25f0dSDavid C Somayajulu {
622711e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
622811e25f0dSDavid C Somayajulu 
622911e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
623011e25f0dSDavid C Somayajulu 
623111e25f0dSDavid C Somayajulu 	bzero((void *)&txq->sw_tx_ring[0],
623211e25f0dSDavid C Somayajulu 		(sizeof (struct sw_tx_bd) * TX_RING_SIZE));
623311e25f0dSDavid C Somayajulu 
623411e25f0dSDavid C Somayajulu         /* Free the real RQ ring used by FW */
623511e25f0dSDavid C Somayajulu         if (txq->tx_pbl.p_virt_addr) {
623611e25f0dSDavid C Somayajulu                 ecore_chain_free(cdev, &txq->tx_pbl);
623711e25f0dSDavid C Somayajulu                 txq->tx_pbl.p_virt_addr = NULL;
623811e25f0dSDavid C Somayajulu         }
623911e25f0dSDavid C Somayajulu 	return;
624011e25f0dSDavid C Somayajulu }
624111e25f0dSDavid C Somayajulu 
624211e25f0dSDavid C Somayajulu /* This function allocates all memory needed per Tx queue */
624311e25f0dSDavid C Somayajulu static int
qlnx_alloc_mem_txq(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_tx_queue * txq)624411e25f0dSDavid C Somayajulu qlnx_alloc_mem_txq(qlnx_host_t *ha, struct qlnx_fastpath *fp,
624511e25f0dSDavid C Somayajulu 	struct qlnx_tx_queue *txq)
624611e25f0dSDavid C Somayajulu {
624711e25f0dSDavid C Somayajulu         int			ret = ECORE_SUCCESS;
624811e25f0dSDavid C Somayajulu         union eth_tx_bd_types	*p_virt;
624911e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
625011e25f0dSDavid C Somayajulu 
625111e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
625211e25f0dSDavid C Somayajulu 
625311e25f0dSDavid C Somayajulu 	bzero((void *)&txq->sw_tx_ring[0],
625411e25f0dSDavid C Somayajulu 		(sizeof (struct sw_tx_bd) * TX_RING_SIZE));
625511e25f0dSDavid C Somayajulu 
625611e25f0dSDavid C Somayajulu         /* Allocate the real Tx ring to be used by FW */
625711e25f0dSDavid C Somayajulu         ret = ecore_chain_alloc(cdev,
625811e25f0dSDavid C Somayajulu                         ECORE_CHAIN_USE_TO_CONSUME_PRODUCE,
625911e25f0dSDavid C Somayajulu                         ECORE_CHAIN_MODE_PBL,
626011e25f0dSDavid C Somayajulu 			ECORE_CHAIN_CNT_TYPE_U16,
626111e25f0dSDavid C Somayajulu                         TX_RING_SIZE,
626211e25f0dSDavid C Somayajulu                         sizeof(*p_virt),
626311e25f0dSDavid C Somayajulu                         &txq->tx_pbl, NULL);
626411e25f0dSDavid C Somayajulu 
626511e25f0dSDavid C Somayajulu         if (ret != ECORE_SUCCESS) {
626611e25f0dSDavid C Somayajulu                 goto err;
626711e25f0dSDavid C Somayajulu         }
626811e25f0dSDavid C Somayajulu 
626911e25f0dSDavid C Somayajulu 	txq->num_tx_buffers = TX_RING_SIZE;
627011e25f0dSDavid C Somayajulu 
627111e25f0dSDavid C Somayajulu         return 0;
627211e25f0dSDavid C Somayajulu 
627311e25f0dSDavid C Somayajulu err:
627411e25f0dSDavid C Somayajulu         qlnx_free_mem_txq(ha, fp, txq);
627511e25f0dSDavid C Somayajulu         return -ENOMEM;
627611e25f0dSDavid C Somayajulu }
627711e25f0dSDavid C Somayajulu 
627811e25f0dSDavid C Somayajulu static void
qlnx_free_tx_br(qlnx_host_t * ha,struct qlnx_fastpath * fp)627911e25f0dSDavid C Somayajulu qlnx_free_tx_br(qlnx_host_t *ha, struct qlnx_fastpath *fp)
628011e25f0dSDavid C Somayajulu {
628111e25f0dSDavid C Somayajulu 	struct mbuf	*mp;
6282727bfe38SJustin Hibbits 	if_t		ifp = ha->ifp;
628311e25f0dSDavid C Somayajulu 
628411e25f0dSDavid C Somayajulu 	if (mtx_initialized(&fp->tx_mtx)) {
628511e25f0dSDavid C Somayajulu 		if (fp->tx_br != NULL) {
628611e25f0dSDavid C Somayajulu 			mtx_lock(&fp->tx_mtx);
628711e25f0dSDavid C Somayajulu 
628811e25f0dSDavid C Somayajulu 			while ((mp = drbr_dequeue(ifp, fp->tx_br)) != NULL) {
628911e25f0dSDavid C Somayajulu 				fp->tx_pkts_freed++;
629011e25f0dSDavid C Somayajulu 				m_freem(mp);
629111e25f0dSDavid C Somayajulu 			}
629211e25f0dSDavid C Somayajulu 
629311e25f0dSDavid C Somayajulu 			mtx_unlock(&fp->tx_mtx);
629411e25f0dSDavid C Somayajulu 
629511e25f0dSDavid C Somayajulu 			buf_ring_free(fp->tx_br, M_DEVBUF);
629611e25f0dSDavid C Somayajulu 			fp->tx_br = NULL;
629711e25f0dSDavid C Somayajulu 		}
629811e25f0dSDavid C Somayajulu 		mtx_destroy(&fp->tx_mtx);
629911e25f0dSDavid C Somayajulu 	}
630011e25f0dSDavid C Somayajulu 	return;
630111e25f0dSDavid C Somayajulu }
630211e25f0dSDavid C Somayajulu 
630311e25f0dSDavid C Somayajulu static void
qlnx_free_mem_fp(qlnx_host_t * ha,struct qlnx_fastpath * fp)630411e25f0dSDavid C Somayajulu qlnx_free_mem_fp(qlnx_host_t *ha, struct qlnx_fastpath *fp)
630511e25f0dSDavid C Somayajulu {
630611e25f0dSDavid C Somayajulu         int	tc;
630711e25f0dSDavid C Somayajulu 
630811e25f0dSDavid C Somayajulu         qlnx_free_mem_sb(ha, fp->sb_info);
630911e25f0dSDavid C Somayajulu 
631011e25f0dSDavid C Somayajulu         qlnx_free_mem_rxq(ha, fp->rxq);
631111e25f0dSDavid C Somayajulu 
631211e25f0dSDavid C Somayajulu         for (tc = 0; tc < ha->num_tc; tc++)
631311e25f0dSDavid C Somayajulu                 qlnx_free_mem_txq(ha, fp, fp->txq[tc]);
631411e25f0dSDavid C Somayajulu 
631511e25f0dSDavid C Somayajulu 	return;
631611e25f0dSDavid C Somayajulu }
631711e25f0dSDavid C Somayajulu 
631811e25f0dSDavid C Somayajulu static int
qlnx_alloc_tx_br(qlnx_host_t * ha,struct qlnx_fastpath * fp)631911e25f0dSDavid C Somayajulu qlnx_alloc_tx_br(qlnx_host_t *ha, struct qlnx_fastpath *fp)
632011e25f0dSDavid C Somayajulu {
632111e25f0dSDavid C Somayajulu 	snprintf(fp->tx_mtx_name, sizeof(fp->tx_mtx_name),
632211e25f0dSDavid C Somayajulu 		"qlnx%d_fp%d_tx_mq_lock", ha->dev_unit, fp->rss_id);
632311e25f0dSDavid C Somayajulu 
632411e25f0dSDavid C Somayajulu 	mtx_init(&fp->tx_mtx, fp->tx_mtx_name, NULL, MTX_DEF);
632511e25f0dSDavid C Somayajulu 
632611e25f0dSDavid C Somayajulu         fp->tx_br = buf_ring_alloc(TX_RING_SIZE, M_DEVBUF,
632711e25f0dSDavid C Somayajulu                                    M_NOWAIT, &fp->tx_mtx);
632811e25f0dSDavid C Somayajulu         if (fp->tx_br == NULL) {
63297a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "buf_ring_alloc failed for fp[%d, %d]\n",
63307a377fbeSDavid C Somayajulu 			ha->dev_unit, fp->rss_id);
633111e25f0dSDavid C Somayajulu 		return -ENOMEM;
633211e25f0dSDavid C Somayajulu         }
633311e25f0dSDavid C Somayajulu 	return 0;
633411e25f0dSDavid C Somayajulu }
633511e25f0dSDavid C Somayajulu 
633611e25f0dSDavid C Somayajulu static int
qlnx_alloc_mem_fp(qlnx_host_t * ha,struct qlnx_fastpath * fp)633711e25f0dSDavid C Somayajulu qlnx_alloc_mem_fp(qlnx_host_t *ha, struct qlnx_fastpath *fp)
633811e25f0dSDavid C Somayajulu {
633911e25f0dSDavid C Somayajulu         int	rc, tc;
634011e25f0dSDavid C Somayajulu 
634111e25f0dSDavid C Somayajulu         rc = qlnx_alloc_mem_sb(ha, fp->sb_info, fp->rss_id);
634211e25f0dSDavid C Somayajulu         if (rc)
634311e25f0dSDavid C Somayajulu                 goto err;
634411e25f0dSDavid C Somayajulu 
634511e25f0dSDavid C Somayajulu 	if (ha->rx_jumbo_buf_eq_mtu) {
634611e25f0dSDavid C Somayajulu 		if (ha->max_frame_size <= MCLBYTES)
634711e25f0dSDavid C Somayajulu 			ha->rx_buf_size = MCLBYTES;
634811e25f0dSDavid C Somayajulu 		else if (ha->max_frame_size <= MJUMPAGESIZE)
634911e25f0dSDavid C Somayajulu 			ha->rx_buf_size = MJUMPAGESIZE;
635011e25f0dSDavid C Somayajulu 		else if (ha->max_frame_size <= MJUM9BYTES)
635111e25f0dSDavid C Somayajulu 			ha->rx_buf_size = MJUM9BYTES;
635211e25f0dSDavid C Somayajulu 		else if (ha->max_frame_size <= MJUM16BYTES)
635311e25f0dSDavid C Somayajulu 			ha->rx_buf_size = MJUM16BYTES;
635411e25f0dSDavid C Somayajulu 	} else {
635511e25f0dSDavid C Somayajulu 		if (ha->max_frame_size <= MCLBYTES)
635611e25f0dSDavid C Somayajulu 			ha->rx_buf_size = MCLBYTES;
635711e25f0dSDavid C Somayajulu 		else
635811e25f0dSDavid C Somayajulu 			ha->rx_buf_size = MJUMPAGESIZE;
635911e25f0dSDavid C Somayajulu 	}
636011e25f0dSDavid C Somayajulu 
636111e25f0dSDavid C Somayajulu         rc = qlnx_alloc_mem_rxq(ha, fp->rxq);
636211e25f0dSDavid C Somayajulu         if (rc)
636311e25f0dSDavid C Somayajulu                 goto err;
636411e25f0dSDavid C Somayajulu 
636511e25f0dSDavid C Somayajulu         for (tc = 0; tc < ha->num_tc; tc++) {
636611e25f0dSDavid C Somayajulu                 rc = qlnx_alloc_mem_txq(ha, fp, fp->txq[tc]);
636711e25f0dSDavid C Somayajulu                 if (rc)
636811e25f0dSDavid C Somayajulu                         goto err;
636911e25f0dSDavid C Somayajulu         }
637011e25f0dSDavid C Somayajulu 
637111e25f0dSDavid C Somayajulu         return 0;
637211e25f0dSDavid C Somayajulu 
637311e25f0dSDavid C Somayajulu err:
637411e25f0dSDavid C Somayajulu         qlnx_free_mem_fp(ha, fp);
637511e25f0dSDavid C Somayajulu         return -ENOMEM;
637611e25f0dSDavid C Somayajulu }
637711e25f0dSDavid C Somayajulu 
637811e25f0dSDavid C Somayajulu static void
qlnx_free_mem_load(qlnx_host_t * ha)637911e25f0dSDavid C Somayajulu qlnx_free_mem_load(qlnx_host_t *ha)
638011e25f0dSDavid C Somayajulu {
638111e25f0dSDavid C Somayajulu         int			i;
638211e25f0dSDavid C Somayajulu 
638311e25f0dSDavid C Somayajulu         for (i = 0; i < ha->num_rss; i++) {
638411e25f0dSDavid C Somayajulu                 struct qlnx_fastpath *fp = &ha->fp_array[i];
638511e25f0dSDavid C Somayajulu 
638611e25f0dSDavid C Somayajulu                 qlnx_free_mem_fp(ha, fp);
638711e25f0dSDavid C Somayajulu         }
638811e25f0dSDavid C Somayajulu 	return;
638911e25f0dSDavid C Somayajulu }
639011e25f0dSDavid C Somayajulu 
639111e25f0dSDavid C Somayajulu static int
qlnx_alloc_mem_load(qlnx_host_t * ha)639211e25f0dSDavid C Somayajulu qlnx_alloc_mem_load(qlnx_host_t *ha)
639311e25f0dSDavid C Somayajulu {
639411e25f0dSDavid C Somayajulu         int	rc = 0, rss_id;
639511e25f0dSDavid C Somayajulu 
639611e25f0dSDavid C Somayajulu         for (rss_id = 0; rss_id < ha->num_rss; rss_id++) {
639711e25f0dSDavid C Somayajulu                 struct qlnx_fastpath *fp = &ha->fp_array[rss_id];
639811e25f0dSDavid C Somayajulu 
639911e25f0dSDavid C Somayajulu                 rc = qlnx_alloc_mem_fp(ha, fp);
640011e25f0dSDavid C Somayajulu                 if (rc)
640111e25f0dSDavid C Somayajulu                         break;
640211e25f0dSDavid C Somayajulu         }
640311e25f0dSDavid C Somayajulu 	return (rc);
640411e25f0dSDavid C Somayajulu }
640511e25f0dSDavid C Somayajulu 
640611e25f0dSDavid C Somayajulu static int
qlnx_start_vport(struct ecore_dev * cdev,u8 vport_id,u16 mtu,u8 drop_ttl0_flg,u8 inner_vlan_removal_en_flg,u8 tx_switching,u8 hw_lro_enable)640711e25f0dSDavid C Somayajulu qlnx_start_vport(struct ecore_dev *cdev,
640811e25f0dSDavid C Somayajulu                 u8 vport_id,
640911e25f0dSDavid C Somayajulu                 u16 mtu,
641011e25f0dSDavid C Somayajulu                 u8 drop_ttl0_flg,
641111e25f0dSDavid C Somayajulu                 u8 inner_vlan_removal_en_flg,
641211e25f0dSDavid C Somayajulu 		u8 tx_switching,
641311e25f0dSDavid C Somayajulu 		u8 hw_lro_enable)
641411e25f0dSDavid C Somayajulu {
641511e25f0dSDavid C Somayajulu         int					rc, i;
641611e25f0dSDavid C Somayajulu 	struct ecore_sp_vport_start_params	vport_start_params = { 0 };
6417eb147f78SJohn Baldwin 	qlnx_host_t				*ha __unused;
641811e25f0dSDavid C Somayajulu 
641911e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)cdev;
642011e25f0dSDavid C Somayajulu 
642111e25f0dSDavid C Somayajulu 	vport_start_params.remove_inner_vlan = inner_vlan_removal_en_flg;
642211e25f0dSDavid C Somayajulu 	vport_start_params.tx_switching = 0;
642311e25f0dSDavid C Somayajulu 	vport_start_params.handle_ptp_pkts = 0;
642411e25f0dSDavid C Somayajulu 	vport_start_params.only_untagged = 0;
642511e25f0dSDavid C Somayajulu 	vport_start_params.drop_ttl0 = drop_ttl0_flg;
642611e25f0dSDavid C Somayajulu 
642711e25f0dSDavid C Somayajulu 	vport_start_params.tpa_mode =
642811e25f0dSDavid C Somayajulu 		(hw_lro_enable ? ECORE_TPA_MODE_RSC : ECORE_TPA_MODE_NONE);
642911e25f0dSDavid C Somayajulu 	vport_start_params.max_buffers_per_cqe = QLNX_TPA_MAX_AGG_BUFFERS;
643011e25f0dSDavid C Somayajulu 
643111e25f0dSDavid C Somayajulu 	vport_start_params.vport_id = vport_id;
643211e25f0dSDavid C Somayajulu 	vport_start_params.mtu = mtu;
643311e25f0dSDavid C Somayajulu 
64347a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "Setting mtu to %d and VPORT ID = %d\n", mtu, vport_id);
643511e25f0dSDavid C Somayajulu 
643611e25f0dSDavid C Somayajulu         for_each_hwfn(cdev, i) {
643711e25f0dSDavid C Somayajulu                 struct ecore_hwfn *p_hwfn = &cdev->hwfns[i];
643811e25f0dSDavid C Somayajulu 
643911e25f0dSDavid C Somayajulu 		vport_start_params.concrete_fid = p_hwfn->hw_info.concrete_fid;
644011e25f0dSDavid C Somayajulu 		vport_start_params.opaque_fid = p_hwfn->hw_info.opaque_fid;
644111e25f0dSDavid C Somayajulu 
644211e25f0dSDavid C Somayajulu                 rc = ecore_sp_vport_start(p_hwfn, &vport_start_params);
644311e25f0dSDavid C Somayajulu 
644411e25f0dSDavid C Somayajulu                 if (rc) {
64457a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "Failed to start VPORT V-PORT %d"
64467a377fbeSDavid C Somayajulu 				" with MTU %d\n" , vport_id, mtu);
644711e25f0dSDavid C Somayajulu                         return -ENOMEM;
644811e25f0dSDavid C Somayajulu                 }
644911e25f0dSDavid C Somayajulu 
645011e25f0dSDavid C Somayajulu                 ecore_hw_start_fastpath(p_hwfn);
645111e25f0dSDavid C Somayajulu 
64527a377fbeSDavid C Somayajulu 		QL_DPRINT2(ha, "Started V-PORT %d with MTU %d\n",
64537a377fbeSDavid C Somayajulu 			vport_id, mtu);
645411e25f0dSDavid C Somayajulu         }
645511e25f0dSDavid C Somayajulu         return 0;
645611e25f0dSDavid C Somayajulu }
645711e25f0dSDavid C Somayajulu 
645811e25f0dSDavid C Somayajulu static int
qlnx_update_vport(struct ecore_dev * cdev,struct qlnx_update_vport_params * params)645911e25f0dSDavid C Somayajulu qlnx_update_vport(struct ecore_dev *cdev,
646011e25f0dSDavid C Somayajulu 	struct qlnx_update_vport_params *params)
646111e25f0dSDavid C Somayajulu {
646211e25f0dSDavid C Somayajulu         struct ecore_sp_vport_update_params	sp_params;
646311e25f0dSDavid C Somayajulu         int					rc, i, j, fp_index;
646411e25f0dSDavid C Somayajulu 	struct ecore_hwfn			*p_hwfn;
646511e25f0dSDavid C Somayajulu         struct ecore_rss_params			*rss;
646611e25f0dSDavid C Somayajulu 	qlnx_host_t				*ha = (qlnx_host_t *)cdev;
646711e25f0dSDavid C Somayajulu         struct qlnx_fastpath			*fp;
646811e25f0dSDavid C Somayajulu 
646911e25f0dSDavid C Somayajulu         memset(&sp_params, 0, sizeof(sp_params));
647011e25f0dSDavid C Somayajulu         /* Translate protocol params into sp params */
647111e25f0dSDavid C Somayajulu         sp_params.vport_id = params->vport_id;
647211e25f0dSDavid C Somayajulu 
647311e25f0dSDavid C Somayajulu         sp_params.update_vport_active_rx_flg =
647411e25f0dSDavid C Somayajulu 		params->update_vport_active_rx_flg;
647511e25f0dSDavid C Somayajulu         sp_params.vport_active_rx_flg = params->vport_active_rx_flg;
647611e25f0dSDavid C Somayajulu 
647711e25f0dSDavid C Somayajulu         sp_params.update_vport_active_tx_flg =
647811e25f0dSDavid C Somayajulu 		params->update_vport_active_tx_flg;
647911e25f0dSDavid C Somayajulu         sp_params.vport_active_tx_flg = params->vport_active_tx_flg;
648011e25f0dSDavid C Somayajulu 
648111e25f0dSDavid C Somayajulu         sp_params.update_inner_vlan_removal_flg =
648211e25f0dSDavid C Somayajulu                 params->update_inner_vlan_removal_flg;
648311e25f0dSDavid C Somayajulu         sp_params.inner_vlan_removal_flg = params->inner_vlan_removal_flg;
648411e25f0dSDavid C Somayajulu 
648511e25f0dSDavid C Somayajulu 	sp_params.sge_tpa_params = params->sge_tpa_params;
648611e25f0dSDavid C Somayajulu 
648711e25f0dSDavid C Somayajulu         /* RSS - is a bit tricky, since upper-layer isn't familiar with hwfns.
648811e25f0dSDavid C Somayajulu          * We need to re-fix the rss values per engine for CMT.
648911e25f0dSDavid C Somayajulu          */
64907a377fbeSDavid C Somayajulu 	if (params->rss_params->update_rss_config)
649111e25f0dSDavid C Somayajulu         sp_params.rss_params = params->rss_params;
64927a377fbeSDavid C Somayajulu 	else
64937a377fbeSDavid C Somayajulu 		sp_params.rss_params =  NULL;
649411e25f0dSDavid C Somayajulu 
649511e25f0dSDavid C Somayajulu         for_each_hwfn(cdev, i) {
649611e25f0dSDavid C Somayajulu 		p_hwfn = &cdev->hwfns[i];
649711e25f0dSDavid C Somayajulu 
649811e25f0dSDavid C Somayajulu 		if ((cdev->num_hwfns > 1) &&
649911e25f0dSDavid C Somayajulu 			params->rss_params->update_rss_config &&
650011e25f0dSDavid C Somayajulu 			params->rss_params->rss_enable) {
650111e25f0dSDavid C Somayajulu 			rss = params->rss_params;
650211e25f0dSDavid C Somayajulu 
650311e25f0dSDavid C Somayajulu 			for (j = 0; j < ECORE_RSS_IND_TABLE_SIZE; j++) {
650411e25f0dSDavid C Somayajulu 				fp_index = ((cdev->num_hwfns * j) + i) %
650511e25f0dSDavid C Somayajulu 						ha->num_rss;
650611e25f0dSDavid C Somayajulu 
650711e25f0dSDavid C Somayajulu                 		fp = &ha->fp_array[fp_index];
6508d6d22a05SDavid C Somayajulu                         	rss->rss_ind_table[j] = fp->rxq->handle;
650911e25f0dSDavid C Somayajulu 			}
651011e25f0dSDavid C Somayajulu 
651111e25f0dSDavid C Somayajulu 			for (j = 0; j < ECORE_RSS_IND_TABLE_SIZE;) {
65127a377fbeSDavid C Somayajulu 				QL_DPRINT3(ha, "%p %p %p %p %p %p %p %p \n",
651311e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j],
651411e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j+1],
651511e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j+2],
651611e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j+3],
651711e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j+4],
651811e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j+5],
651911e25f0dSDavid C Somayajulu 					rss->rss_ind_table[j+6],
65207a377fbeSDavid C Somayajulu 					rss->rss_ind_table[j+7]);
652111e25f0dSDavid C Somayajulu 					j += 8;
652211e25f0dSDavid C Somayajulu 			}
652311e25f0dSDavid C Somayajulu 		}
652411e25f0dSDavid C Somayajulu 
652511e25f0dSDavid C Somayajulu                 sp_params.opaque_fid = p_hwfn->hw_info.opaque_fid;
65267a377fbeSDavid C Somayajulu 
65277a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "Update sp vport ID=%d\n", params->vport_id);
65287a377fbeSDavid C Somayajulu 
652911e25f0dSDavid C Somayajulu                 rc = ecore_sp_vport_update(p_hwfn, &sp_params,
653011e25f0dSDavid C Somayajulu                                            ECORE_SPQ_MODE_EBLOCK, NULL);
653111e25f0dSDavid C Somayajulu                 if (rc) {
65327a377fbeSDavid C Somayajulu 			QL_DPRINT1(ha, "Failed to update VPORT\n");
653311e25f0dSDavid C Somayajulu                         return rc;
653411e25f0dSDavid C Somayajulu                 }
653511e25f0dSDavid C Somayajulu 
65367a377fbeSDavid C Somayajulu                 QL_DPRINT2(ha, "Updated V-PORT %d: tx_active_flag %d, \
65377a377fbeSDavid C Somayajulu 			rx_active_flag %d [tx_update %d], [rx_update %d]\n",
653811e25f0dSDavid C Somayajulu 			params->vport_id, params->vport_active_tx_flg,
653911e25f0dSDavid C Somayajulu 			params->vport_active_rx_flg,
654011e25f0dSDavid C Somayajulu 			params->update_vport_active_tx_flg,
65417a377fbeSDavid C Somayajulu 			params->update_vport_active_rx_flg);
654211e25f0dSDavid C Somayajulu         }
654311e25f0dSDavid C Somayajulu 
654411e25f0dSDavid C Somayajulu         return 0;
654511e25f0dSDavid C Somayajulu }
654611e25f0dSDavid C Somayajulu 
654711e25f0dSDavid C Somayajulu static void
qlnx_reuse_rx_data(struct qlnx_rx_queue * rxq)654811e25f0dSDavid C Somayajulu qlnx_reuse_rx_data(struct qlnx_rx_queue *rxq)
654911e25f0dSDavid C Somayajulu {
655011e25f0dSDavid C Somayajulu         struct eth_rx_bd	*rx_bd_cons =
655111e25f0dSDavid C Somayajulu 					ecore_chain_consume(&rxq->rx_bd_ring);
655211e25f0dSDavid C Somayajulu         struct eth_rx_bd	*rx_bd_prod =
655311e25f0dSDavid C Somayajulu 					ecore_chain_produce(&rxq->rx_bd_ring);
655411e25f0dSDavid C Somayajulu         struct sw_rx_data	*sw_rx_data_cons =
655511e25f0dSDavid C Somayajulu 					&rxq->sw_rx_ring[rxq->sw_rx_cons];
655611e25f0dSDavid C Somayajulu         struct sw_rx_data	*sw_rx_data_prod =
655711e25f0dSDavid C Somayajulu 					&rxq->sw_rx_ring[rxq->sw_rx_prod];
655811e25f0dSDavid C Somayajulu 
655911e25f0dSDavid C Somayajulu         sw_rx_data_prod->data = sw_rx_data_cons->data;
656011e25f0dSDavid C Somayajulu         memcpy(rx_bd_prod, rx_bd_cons, sizeof(struct eth_rx_bd));
656111e25f0dSDavid C Somayajulu 
656211e25f0dSDavid C Somayajulu         rxq->sw_rx_cons  = (rxq->sw_rx_cons + 1) & (RX_RING_SIZE - 1);
656311e25f0dSDavid C Somayajulu         rxq->sw_rx_prod  = (rxq->sw_rx_prod + 1) & (RX_RING_SIZE - 1);
656411e25f0dSDavid C Somayajulu 
656511e25f0dSDavid C Somayajulu 	return;
656611e25f0dSDavid C Somayajulu }
656711e25f0dSDavid C Somayajulu 
656811e25f0dSDavid C Somayajulu static void
qlnx_update_rx_prod(struct ecore_hwfn * p_hwfn,struct qlnx_rx_queue * rxq)656911e25f0dSDavid C Somayajulu qlnx_update_rx_prod(struct ecore_hwfn *p_hwfn, struct qlnx_rx_queue *rxq)
657011e25f0dSDavid C Somayajulu {
657111e25f0dSDavid C Somayajulu 
657211e25f0dSDavid C Somayajulu         uint16_t	 	bd_prod;
657311e25f0dSDavid C Somayajulu         uint16_t		cqe_prod;
657454064a2fSDavid C Somayajulu 	union {
657554064a2fSDavid C Somayajulu 		struct eth_rx_prod_data rx_prod_data;
657654064a2fSDavid C Somayajulu 		uint32_t		data32;
657754064a2fSDavid C Somayajulu 	} rx_prods;
657811e25f0dSDavid C Somayajulu 
657911e25f0dSDavid C Somayajulu         bd_prod = ecore_chain_get_prod_idx(&rxq->rx_bd_ring);
658011e25f0dSDavid C Somayajulu         cqe_prod = ecore_chain_get_prod_idx(&rxq->rx_comp_ring);
658111e25f0dSDavid C Somayajulu 
658211e25f0dSDavid C Somayajulu         /* Update producers */
658354064a2fSDavid C Somayajulu         rx_prods.rx_prod_data.bd_prod = htole16(bd_prod);
658454064a2fSDavid C Somayajulu         rx_prods.rx_prod_data.cqe_prod = htole16(cqe_prod);
658511e25f0dSDavid C Somayajulu 
658611e25f0dSDavid C Somayajulu         /* Make sure that the BD and SGE data is updated before updating the
658711e25f0dSDavid C Somayajulu          * producers since FW might read the BD/SGE right after the producer
658811e25f0dSDavid C Somayajulu          * is updated.
658911e25f0dSDavid C Somayajulu          */
659011e25f0dSDavid C Somayajulu 	wmb();
659111e25f0dSDavid C Somayajulu 
6592c1be7151SMark O'Donovan #ifdef ECORE_CONFIG_DIRECT_HWFN
659311e25f0dSDavid C Somayajulu 	internal_ram_wr(p_hwfn, rxq->hw_rxq_prod_addr,
659454064a2fSDavid C Somayajulu 		sizeof(rx_prods), &rx_prods.data32);
6595c1be7151SMark O'Donovan #else
6596c1be7151SMark O'Donovan 	internal_ram_wr(rxq->hw_rxq_prod_addr,
6597c1be7151SMark O'Donovan 		sizeof(rx_prods), &rx_prods.data32);
6598c1be7151SMark O'Donovan #endif
659911e25f0dSDavid C Somayajulu 
660011e25f0dSDavid C Somayajulu         /* mmiowb is needed to synchronize doorbell writes from more than one
660111e25f0dSDavid C Somayajulu          * processor. It guarantees that the write arrives to the device before
660211e25f0dSDavid C Somayajulu          * the napi lock is released and another qlnx_poll is called (possibly
660311e25f0dSDavid C Somayajulu          * on another CPU). Without this barrier, the next doorbell can bypass
660411e25f0dSDavid C Somayajulu          * this doorbell. This is applicable to IA64/Altix systems.
660511e25f0dSDavid C Somayajulu          */
660611e25f0dSDavid C Somayajulu         wmb();
660711e25f0dSDavid C Somayajulu 
660811e25f0dSDavid C Somayajulu 	return;
660911e25f0dSDavid C Somayajulu }
661011e25f0dSDavid C Somayajulu 
661111e25f0dSDavid C Somayajulu static uint32_t qlnx_hash_key[] = {
661211e25f0dSDavid C Somayajulu                 ((0x6d << 24)|(0x5a << 16)|(0x56 << 8)|0xda),
661311e25f0dSDavid C Somayajulu                 ((0x25 << 24)|(0x5b << 16)|(0x0e << 8)|0xc2),
661411e25f0dSDavid C Somayajulu                 ((0x41 << 24)|(0x67 << 16)|(0x25 << 8)|0x3d),
661511e25f0dSDavid C Somayajulu                 ((0x43 << 24)|(0xa3 << 16)|(0x8f << 8)|0xb0),
661611e25f0dSDavid C Somayajulu                 ((0xd0 << 24)|(0xca << 16)|(0x2b << 8)|0xcb),
661711e25f0dSDavid C Somayajulu                 ((0xae << 24)|(0x7b << 16)|(0x30 << 8)|0xb4),
661811e25f0dSDavid C Somayajulu                 ((0x77 << 24)|(0xcb << 16)|(0x2d << 8)|0xa3),
661911e25f0dSDavid C Somayajulu                 ((0x80 << 24)|(0x30 << 16)|(0xf2 << 8)|0x0c),
662011e25f0dSDavid C Somayajulu                 ((0x6a << 24)|(0x42 << 16)|(0xb7 << 8)|0x3b),
662111e25f0dSDavid C Somayajulu                 ((0xbe << 24)|(0xac << 16)|(0x01 << 8)|0xfa)};
662211e25f0dSDavid C Somayajulu 
662311e25f0dSDavid C Somayajulu static int
qlnx_start_queues(qlnx_host_t * ha)662411e25f0dSDavid C Somayajulu qlnx_start_queues(qlnx_host_t *ha)
662511e25f0dSDavid C Somayajulu {
662611e25f0dSDavid C Somayajulu         int				rc, tc, i, vport_id = 0,
662711e25f0dSDavid C Somayajulu 					drop_ttl0_flg = 1, vlan_removal_en = 1,
662811e25f0dSDavid C Somayajulu 					tx_switching = 0, hw_lro_enable = 0;
662911e25f0dSDavid C Somayajulu         struct ecore_dev		*cdev = &ha->cdev;
663011e25f0dSDavid C Somayajulu         struct ecore_rss_params		*rss_params = &ha->rss_params;
663111e25f0dSDavid C Somayajulu         struct qlnx_update_vport_params	vport_update_params;
6632727bfe38SJustin Hibbits         if_t				ifp;
663311e25f0dSDavid C Somayajulu         struct ecore_hwfn		*p_hwfn;
663411e25f0dSDavid C Somayajulu 	struct ecore_sge_tpa_params	tpa_params;
663511e25f0dSDavid C Somayajulu 	struct ecore_queue_start_common_params qparams;
663611e25f0dSDavid C Somayajulu         struct qlnx_fastpath		*fp;
663711e25f0dSDavid C Somayajulu 
663811e25f0dSDavid C Somayajulu 	ifp = ha->ifp;
663911e25f0dSDavid C Somayajulu 
66407a377fbeSDavid C Somayajulu 	QL_DPRINT1(ha, "Num RSS = %d\n", ha->num_rss);
66417a377fbeSDavid C Somayajulu 
664211e25f0dSDavid C Somayajulu         if (!ha->num_rss) {
66437a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "Cannot update V-VPORT as active as there"
66447a377fbeSDavid C Somayajulu 			" are no Rx queues\n");
664511e25f0dSDavid C Somayajulu                 return -EINVAL;
664611e25f0dSDavid C Somayajulu         }
664711e25f0dSDavid C Somayajulu 
664811e25f0dSDavid C Somayajulu #ifndef QLNX_SOFT_LRO
6649727bfe38SJustin Hibbits         hw_lro_enable = if_getcapenable(ifp) & IFCAP_LRO;
665011e25f0dSDavid C Somayajulu #endif /* #ifndef QLNX_SOFT_LRO */
665111e25f0dSDavid C Somayajulu 
6652727bfe38SJustin Hibbits         rc = qlnx_start_vport(cdev, vport_id, if_getmtu(ifp), drop_ttl0_flg,
665311e25f0dSDavid C Somayajulu 			vlan_removal_en, tx_switching, hw_lro_enable);
665411e25f0dSDavid C Somayajulu 
665511e25f0dSDavid C Somayajulu         if (rc) {
66567a377fbeSDavid C Somayajulu                 QL_DPRINT1(ha, "Start V-PORT failed %d\n", rc);
665711e25f0dSDavid C Somayajulu                 return rc;
665811e25f0dSDavid C Somayajulu         }
665911e25f0dSDavid C Somayajulu 
66607a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "Start vport ramrod passed, "
66617a377fbeSDavid C Somayajulu 		"vport_id = %d, MTU = %d, vlan_removal_en = %d\n",
6662727bfe38SJustin Hibbits 		vport_id, (int)(if_getmtu(ifp) + 0xe), vlan_removal_en);
666311e25f0dSDavid C Somayajulu 
666411e25f0dSDavid C Somayajulu         for_each_rss(i) {
666511e25f0dSDavid C Somayajulu 		struct ecore_rxq_start_ret_params rx_ret_params;
666611e25f0dSDavid C Somayajulu 		struct ecore_txq_start_ret_params tx_ret_params;
666711e25f0dSDavid C Somayajulu 
666811e25f0dSDavid C Somayajulu                 fp = &ha->fp_array[i];
666911e25f0dSDavid C Somayajulu         	p_hwfn = &cdev->hwfns[(fp->rss_id % cdev->num_hwfns)];
667011e25f0dSDavid C Somayajulu 
667111e25f0dSDavid C Somayajulu 		bzero(&qparams, sizeof(struct ecore_queue_start_common_params));
667211e25f0dSDavid C Somayajulu 		bzero(&rx_ret_params,
667311e25f0dSDavid C Somayajulu 			sizeof (struct ecore_rxq_start_ret_params));
667411e25f0dSDavid C Somayajulu 
667511e25f0dSDavid C Somayajulu 		qparams.queue_id = i ;
667611e25f0dSDavid C Somayajulu 		qparams.vport_id = vport_id;
667711e25f0dSDavid C Somayajulu 		qparams.stats_id = vport_id;
667811e25f0dSDavid C Somayajulu 		qparams.p_sb = fp->sb_info;
667911e25f0dSDavid C Somayajulu 		qparams.sb_idx = RX_PI;
668011e25f0dSDavid C Somayajulu 
668111e25f0dSDavid C Somayajulu 
668211e25f0dSDavid C Somayajulu 		rc = ecore_eth_rx_queue_start(p_hwfn,
668311e25f0dSDavid C Somayajulu 			p_hwfn->hw_info.opaque_fid,
668411e25f0dSDavid C Somayajulu 			&qparams,
668511e25f0dSDavid C Somayajulu 			fp->rxq->rx_buf_size,	/* bd_max_bytes */
668611e25f0dSDavid C Somayajulu 			/* bd_chain_phys_addr */
668711e25f0dSDavid C Somayajulu 			fp->rxq->rx_bd_ring.p_phys_addr,
668811e25f0dSDavid C Somayajulu 			/* cqe_pbl_addr */
668911e25f0dSDavid C Somayajulu 			ecore_chain_get_pbl_phys(&fp->rxq->rx_comp_ring),
669011e25f0dSDavid C Somayajulu 			/* cqe_pbl_size */
669111e25f0dSDavid C Somayajulu 			ecore_chain_get_page_cnt(&fp->rxq->rx_comp_ring),
669211e25f0dSDavid C Somayajulu 			&rx_ret_params);
669311e25f0dSDavid C Somayajulu 
669411e25f0dSDavid C Somayajulu                 if (rc) {
66957a377fbeSDavid C Somayajulu                 	QL_DPRINT1(ha, "Start RXQ #%d failed %d\n", i, rc);
669611e25f0dSDavid C Somayajulu                         return rc;
669711e25f0dSDavid C Somayajulu                 }
669811e25f0dSDavid C Somayajulu 
669911e25f0dSDavid C Somayajulu 		fp->rxq->hw_rxq_prod_addr	= rx_ret_params.p_prod;
670011e25f0dSDavid C Somayajulu 		fp->rxq->handle			= rx_ret_params.p_handle;
670111e25f0dSDavid C Somayajulu                 fp->rxq->hw_cons_ptr		=
670211e25f0dSDavid C Somayajulu 				&fp->sb_info->sb_virt->pi_array[RX_PI];
670311e25f0dSDavid C Somayajulu 
670411e25f0dSDavid C Somayajulu                 qlnx_update_rx_prod(p_hwfn, fp->rxq);
670511e25f0dSDavid C Somayajulu 
670611e25f0dSDavid C Somayajulu                 for (tc = 0; tc < ha->num_tc; tc++) {
670711e25f0dSDavid C Somayajulu                         struct qlnx_tx_queue *txq = fp->txq[tc];
670811e25f0dSDavid C Somayajulu 
670911e25f0dSDavid C Somayajulu 			bzero(&qparams,
671011e25f0dSDavid C Somayajulu 				sizeof(struct ecore_queue_start_common_params));
671111e25f0dSDavid C Somayajulu 			bzero(&tx_ret_params,
671211e25f0dSDavid C Somayajulu 				sizeof (struct ecore_txq_start_ret_params));
671311e25f0dSDavid C Somayajulu 
671411e25f0dSDavid C Somayajulu 			qparams.queue_id = txq->index / cdev->num_hwfns ;
671511e25f0dSDavid C Somayajulu 			qparams.vport_id = vport_id;
671611e25f0dSDavid C Somayajulu 			qparams.stats_id = vport_id;
671711e25f0dSDavid C Somayajulu 			qparams.p_sb = fp->sb_info;
671811e25f0dSDavid C Somayajulu 			qparams.sb_idx = TX_PI(tc);
671911e25f0dSDavid C Somayajulu 
672011e25f0dSDavid C Somayajulu 			rc = ecore_eth_tx_queue_start(p_hwfn,
672111e25f0dSDavid C Somayajulu 				p_hwfn->hw_info.opaque_fid,
672211e25f0dSDavid C Somayajulu 				&qparams, tc,
672311e25f0dSDavid C Somayajulu 				/* bd_chain_phys_addr */
672411e25f0dSDavid C Somayajulu 				ecore_chain_get_pbl_phys(&txq->tx_pbl),
672511e25f0dSDavid C Somayajulu 				ecore_chain_get_page_cnt(&txq->tx_pbl),
672611e25f0dSDavid C Somayajulu 				&tx_ret_params);
672711e25f0dSDavid C Somayajulu 
672811e25f0dSDavid C Somayajulu                         if (rc) {
67297a377fbeSDavid C Somayajulu                 		QL_DPRINT1(ha, "Start TXQ #%d failed %d\n",
67307a377fbeSDavid C Somayajulu 					   txq->index, rc);
673111e25f0dSDavid C Somayajulu                                 return rc;
673211e25f0dSDavid C Somayajulu                         }
673311e25f0dSDavid C Somayajulu 
673411e25f0dSDavid C Somayajulu 			txq->doorbell_addr = tx_ret_params.p_doorbell;
673511e25f0dSDavid C Somayajulu 			txq->handle = tx_ret_params.p_handle;
673611e25f0dSDavid C Somayajulu 
673711e25f0dSDavid C Somayajulu                         txq->hw_cons_ptr =
673811e25f0dSDavid C Somayajulu                                 &fp->sb_info->sb_virt->pi_array[TX_PI(tc)];
673911e25f0dSDavid C Somayajulu                         SET_FIELD(txq->tx_db.data.params,
674011e25f0dSDavid C Somayajulu                                   ETH_DB_DATA_DEST, DB_DEST_XCM);
674111e25f0dSDavid C Somayajulu                         SET_FIELD(txq->tx_db.data.params, ETH_DB_DATA_AGG_CMD,
674211e25f0dSDavid C Somayajulu                                   DB_AGG_CMD_SET);
674311e25f0dSDavid C Somayajulu                         SET_FIELD(txq->tx_db.data.params,
674411e25f0dSDavid C Somayajulu                                   ETH_DB_DATA_AGG_VAL_SEL,
674511e25f0dSDavid C Somayajulu                                   DQ_XCM_ETH_TX_BD_PROD_CMD);
674611e25f0dSDavid C Somayajulu 
674711e25f0dSDavid C Somayajulu                         txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD;
674811e25f0dSDavid C Somayajulu                 }
674911e25f0dSDavid C Somayajulu         }
675011e25f0dSDavid C Somayajulu 
675111e25f0dSDavid C Somayajulu         /* Fill struct with RSS params */
675211e25f0dSDavid C Somayajulu         if (ha->num_rss > 1) {
675311e25f0dSDavid C Somayajulu                 rss_params->update_rss_config = 1;
675411e25f0dSDavid C Somayajulu                 rss_params->rss_enable = 1;
675511e25f0dSDavid C Somayajulu                 rss_params->update_rss_capabilities = 1;
675611e25f0dSDavid C Somayajulu                 rss_params->update_rss_ind_table = 1;
675711e25f0dSDavid C Somayajulu                 rss_params->update_rss_key = 1;
675811e25f0dSDavid C Somayajulu                 rss_params->rss_caps = ECORE_RSS_IPV4 | ECORE_RSS_IPV6 |
675911e25f0dSDavid C Somayajulu                                        ECORE_RSS_IPV4_TCP | ECORE_RSS_IPV6_TCP;
676011e25f0dSDavid C Somayajulu                 rss_params->rss_table_size_log = 7; /* 2^7 = 128 */
676111e25f0dSDavid C Somayajulu 
676211e25f0dSDavid C Somayajulu                 for (i = 0; i < ECORE_RSS_IND_TABLE_SIZE; i++) {
676311e25f0dSDavid C Somayajulu                 	fp = &ha->fp_array[(i % ha->num_rss)];
676411e25f0dSDavid C Somayajulu                         rss_params->rss_ind_table[i] = fp->rxq->handle;
676511e25f0dSDavid C Somayajulu 		}
676611e25f0dSDavid C Somayajulu 
676711e25f0dSDavid C Somayajulu                 for (i = 0; i < ECORE_RSS_KEY_SIZE; i++)
676811e25f0dSDavid C Somayajulu 			rss_params->rss_key[i] = (__le32)qlnx_hash_key[i];
676911e25f0dSDavid C Somayajulu 
677011e25f0dSDavid C Somayajulu         } else {
677111e25f0dSDavid C Somayajulu                 memset(rss_params, 0, sizeof(*rss_params));
677211e25f0dSDavid C Somayajulu         }
677311e25f0dSDavid C Somayajulu 
677411e25f0dSDavid C Somayajulu         /* Prepare and send the vport enable */
677511e25f0dSDavid C Somayajulu         memset(&vport_update_params, 0, sizeof(vport_update_params));
677611e25f0dSDavid C Somayajulu         vport_update_params.vport_id = vport_id;
677711e25f0dSDavid C Somayajulu         vport_update_params.update_vport_active_tx_flg = 1;
677811e25f0dSDavid C Somayajulu         vport_update_params.vport_active_tx_flg = 1;
677911e25f0dSDavid C Somayajulu         vport_update_params.update_vport_active_rx_flg = 1;
678011e25f0dSDavid C Somayajulu         vport_update_params.vport_active_rx_flg = 1;
678111e25f0dSDavid C Somayajulu         vport_update_params.rss_params = rss_params;
678211e25f0dSDavid C Somayajulu         vport_update_params.update_inner_vlan_removal_flg = 1;
678311e25f0dSDavid C Somayajulu         vport_update_params.inner_vlan_removal_flg = 1;
678411e25f0dSDavid C Somayajulu 
678511e25f0dSDavid C Somayajulu 	if (hw_lro_enable) {
678611e25f0dSDavid C Somayajulu 		memset(&tpa_params, 0, sizeof (struct ecore_sge_tpa_params));
678711e25f0dSDavid C Somayajulu 
678811e25f0dSDavid C Somayajulu 		tpa_params.max_buffers_per_cqe = QLNX_TPA_MAX_AGG_BUFFERS;
678911e25f0dSDavid C Somayajulu 
679011e25f0dSDavid C Somayajulu 		tpa_params.update_tpa_en_flg = 1;
679111e25f0dSDavid C Somayajulu 		tpa_params.tpa_ipv4_en_flg = 1;
679211e25f0dSDavid C Somayajulu 		tpa_params.tpa_ipv6_en_flg = 1;
679311e25f0dSDavid C Somayajulu 
679411e25f0dSDavid C Somayajulu 		tpa_params.update_tpa_param_flg = 1;
679511e25f0dSDavid C Somayajulu 		tpa_params.tpa_pkt_split_flg = 0;
679611e25f0dSDavid C Somayajulu 		tpa_params.tpa_hdr_data_split_flg = 0;
679711e25f0dSDavid C Somayajulu 		tpa_params.tpa_gro_consistent_flg = 0;
679811e25f0dSDavid C Somayajulu 		tpa_params.tpa_max_aggs_num = ETH_TPA_MAX_AGGS_NUM;
679911e25f0dSDavid C Somayajulu 		tpa_params.tpa_max_size = (uint16_t)(-1);
6800727bfe38SJustin Hibbits 		tpa_params.tpa_min_size_to_start = if_getmtu(ifp) / 2;
6801727bfe38SJustin Hibbits 		tpa_params.tpa_min_size_to_cont = if_getmtu(ifp) / 2;
680211e25f0dSDavid C Somayajulu 
680311e25f0dSDavid C Somayajulu 		vport_update_params.sge_tpa_params = &tpa_params;
680411e25f0dSDavid C Somayajulu 	}
680511e25f0dSDavid C Somayajulu 
680611e25f0dSDavid C Somayajulu         rc = qlnx_update_vport(cdev, &vport_update_params);
680711e25f0dSDavid C Somayajulu         if (rc) {
68087a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "Update V-PORT failed %d\n", rc);
680911e25f0dSDavid C Somayajulu                 return rc;
681011e25f0dSDavid C Somayajulu         }
681111e25f0dSDavid C Somayajulu 
681211e25f0dSDavid C Somayajulu         return 0;
681311e25f0dSDavid C Somayajulu }
681411e25f0dSDavid C Somayajulu 
681511e25f0dSDavid C Somayajulu static int
qlnx_drain_txq(qlnx_host_t * ha,struct qlnx_fastpath * fp,struct qlnx_tx_queue * txq)681611e25f0dSDavid C Somayajulu qlnx_drain_txq(qlnx_host_t *ha, struct qlnx_fastpath *fp,
681711e25f0dSDavid C Somayajulu 	struct qlnx_tx_queue *txq)
681811e25f0dSDavid C Somayajulu {
681911e25f0dSDavid C Somayajulu 	uint16_t	hw_bd_cons;
682011e25f0dSDavid C Somayajulu 	uint16_t	ecore_cons_idx;
682111e25f0dSDavid C Somayajulu 
68227a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
682311e25f0dSDavid C Somayajulu 
682411e25f0dSDavid C Somayajulu 	hw_bd_cons = le16toh(*txq->hw_cons_ptr);
682511e25f0dSDavid C Somayajulu 
682611e25f0dSDavid C Somayajulu 	while (hw_bd_cons !=
682711e25f0dSDavid C Somayajulu 		(ecore_cons_idx = ecore_chain_get_cons_idx(&txq->tx_pbl))) {
682811e25f0dSDavid C Somayajulu 		mtx_lock(&fp->tx_mtx);
682911e25f0dSDavid C Somayajulu 
683011e25f0dSDavid C Somayajulu 		(void)qlnx_tx_int(ha, fp, txq);
683111e25f0dSDavid C Somayajulu 
683211e25f0dSDavid C Somayajulu 		mtx_unlock(&fp->tx_mtx);
683311e25f0dSDavid C Somayajulu 
683411e25f0dSDavid C Somayajulu 		qlnx_mdelay(__func__, 2);
683511e25f0dSDavid C Somayajulu 
683611e25f0dSDavid C Somayajulu 		hw_bd_cons = le16toh(*txq->hw_cons_ptr);
683711e25f0dSDavid C Somayajulu 	}
683811e25f0dSDavid C Somayajulu 
68397a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "[%d, %d]: done\n", fp->rss_id, txq->index);
684011e25f0dSDavid C Somayajulu 
684111e25f0dSDavid C Somayajulu         return 0;
684211e25f0dSDavid C Somayajulu }
684311e25f0dSDavid C Somayajulu 
684411e25f0dSDavid C Somayajulu static int
qlnx_stop_queues(qlnx_host_t * ha)684511e25f0dSDavid C Somayajulu qlnx_stop_queues(qlnx_host_t *ha)
684611e25f0dSDavid C Somayajulu {
684711e25f0dSDavid C Somayajulu         struct qlnx_update_vport_params	vport_update_params;
684811e25f0dSDavid C Somayajulu         struct ecore_dev		*cdev;
684911e25f0dSDavid C Somayajulu         struct qlnx_fastpath		*fp;
685011e25f0dSDavid C Somayajulu         int				rc, tc, i;
685111e25f0dSDavid C Somayajulu 
685211e25f0dSDavid C Somayajulu         cdev = &ha->cdev;
685311e25f0dSDavid C Somayajulu 
685411e25f0dSDavid C Somayajulu         /* Disable the vport */
685511e25f0dSDavid C Somayajulu 
685611e25f0dSDavid C Somayajulu         memset(&vport_update_params, 0, sizeof(vport_update_params));
685711e25f0dSDavid C Somayajulu 
685811e25f0dSDavid C Somayajulu         vport_update_params.vport_id = 0;
685911e25f0dSDavid C Somayajulu         vport_update_params.update_vport_active_tx_flg = 1;
686011e25f0dSDavid C Somayajulu         vport_update_params.vport_active_tx_flg = 0;
686111e25f0dSDavid C Somayajulu         vport_update_params.update_vport_active_rx_flg = 1;
686211e25f0dSDavid C Somayajulu         vport_update_params.vport_active_rx_flg = 0;
686311e25f0dSDavid C Somayajulu         vport_update_params.rss_params = &ha->rss_params;
686411e25f0dSDavid C Somayajulu         vport_update_params.rss_params->update_rss_config = 0;
686511e25f0dSDavid C Somayajulu         vport_update_params.rss_params->rss_enable = 0;
686611e25f0dSDavid C Somayajulu         vport_update_params.update_inner_vlan_removal_flg = 0;
686711e25f0dSDavid C Somayajulu         vport_update_params.inner_vlan_removal_flg = 0;
686811e25f0dSDavid C Somayajulu 
68697a377fbeSDavid C Somayajulu 	QL_DPRINT1(ha, "Update vport ID= %d\n", vport_update_params.vport_id);
68707a377fbeSDavid C Somayajulu 
687111e25f0dSDavid C Somayajulu         rc = qlnx_update_vport(cdev, &vport_update_params);
687211e25f0dSDavid C Somayajulu         if (rc) {
68737a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "Failed to update vport\n");
687411e25f0dSDavid C Somayajulu                 return rc;
687511e25f0dSDavid C Somayajulu         }
687611e25f0dSDavid C Somayajulu 
687711e25f0dSDavid C Somayajulu         /* Flush Tx queues. If needed, request drain from MCP */
687811e25f0dSDavid C Somayajulu         for_each_rss(i) {
687911e25f0dSDavid C Somayajulu                 fp = &ha->fp_array[i];
688011e25f0dSDavid C Somayajulu 
688111e25f0dSDavid C Somayajulu                 for (tc = 0; tc < ha->num_tc; tc++) {
688211e25f0dSDavid C Somayajulu                         struct qlnx_tx_queue *txq = fp->txq[tc];
688311e25f0dSDavid C Somayajulu 
688411e25f0dSDavid C Somayajulu                         rc = qlnx_drain_txq(ha, fp, txq);
688511e25f0dSDavid C Somayajulu                         if (rc)
688611e25f0dSDavid C Somayajulu                                 return rc;
688711e25f0dSDavid C Somayajulu                 }
688811e25f0dSDavid C Somayajulu         }
688911e25f0dSDavid C Somayajulu 
689011e25f0dSDavid C Somayajulu         /* Stop all Queues in reverse order*/
689111e25f0dSDavid C Somayajulu         for (i = ha->num_rss - 1; i >= 0; i--) {
689211e25f0dSDavid C Somayajulu 		struct ecore_hwfn *p_hwfn = &cdev->hwfns[(i % cdev->num_hwfns)];
689311e25f0dSDavid C Somayajulu 
689411e25f0dSDavid C Somayajulu                 fp = &ha->fp_array[i];
689511e25f0dSDavid C Somayajulu 
689611e25f0dSDavid C Somayajulu                 /* Stop the Tx Queue(s)*/
689711e25f0dSDavid C Somayajulu                 for (tc = 0; tc < ha->num_tc; tc++) {
6898eb147f78SJohn Baldwin 			int tx_queue_id __unused;
689911e25f0dSDavid C Somayajulu 
690011e25f0dSDavid C Somayajulu 			tx_queue_id = tc * ha->num_rss + i;
690111e25f0dSDavid C Somayajulu 			rc = ecore_eth_tx_queue_stop(p_hwfn,
690211e25f0dSDavid C Somayajulu 					fp->txq[tc]->handle);
690311e25f0dSDavid C Somayajulu 
690411e25f0dSDavid C Somayajulu                         if (rc) {
69057a377fbeSDavid C Somayajulu 				QL_DPRINT1(ha, "Failed to stop TXQ #%d\n",
69067a377fbeSDavid C Somayajulu 					   tx_queue_id);
690711e25f0dSDavid C Somayajulu                                 return rc;
690811e25f0dSDavid C Somayajulu                         }
690911e25f0dSDavid C Somayajulu                 }
691011e25f0dSDavid C Somayajulu 
691111e25f0dSDavid C Somayajulu                 /* Stop the Rx Queue*/
691211e25f0dSDavid C Somayajulu 		rc = ecore_eth_rx_queue_stop(p_hwfn, fp->rxq->handle, false,
691311e25f0dSDavid C Somayajulu 				false);
691411e25f0dSDavid C Somayajulu                 if (rc) {
69157a377fbeSDavid C Somayajulu                         QL_DPRINT1(ha, "Failed to stop RXQ #%d\n", i);
691611e25f0dSDavid C Somayajulu                         return rc;
691711e25f0dSDavid C Somayajulu                 }
691811e25f0dSDavid C Somayajulu         }
691911e25f0dSDavid C Somayajulu 
692011e25f0dSDavid C Somayajulu         /* Stop the vport */
692111e25f0dSDavid C Somayajulu 	for_each_hwfn(cdev, i) {
692211e25f0dSDavid C Somayajulu 		struct ecore_hwfn *p_hwfn = &cdev->hwfns[i];
692311e25f0dSDavid C Somayajulu 
692411e25f0dSDavid C Somayajulu 		rc = ecore_sp_vport_stop(p_hwfn, p_hwfn->hw_info.opaque_fid, 0);
692511e25f0dSDavid C Somayajulu 
692611e25f0dSDavid C Somayajulu 		if (rc) {
69277a377fbeSDavid C Somayajulu                         QL_DPRINT1(ha, "Failed to stop VPORT\n");
692811e25f0dSDavid C Somayajulu 			return rc;
692911e25f0dSDavid C Somayajulu 		}
693011e25f0dSDavid C Somayajulu 	}
693111e25f0dSDavid C Somayajulu 
693211e25f0dSDavid C Somayajulu         return rc;
693311e25f0dSDavid C Somayajulu }
693411e25f0dSDavid C Somayajulu 
693511e25f0dSDavid C Somayajulu static int
qlnx_set_ucast_rx_mac(qlnx_host_t * ha,enum ecore_filter_opcode opcode,unsigned char mac[ETH_ALEN])693611e25f0dSDavid C Somayajulu qlnx_set_ucast_rx_mac(qlnx_host_t *ha,
693711e25f0dSDavid C Somayajulu 	enum ecore_filter_opcode opcode,
693811e25f0dSDavid C Somayajulu 	unsigned char mac[ETH_ALEN])
693911e25f0dSDavid C Somayajulu {
694011e25f0dSDavid C Somayajulu 	struct ecore_filter_ucast	ucast;
694111e25f0dSDavid C Somayajulu 	struct ecore_dev		*cdev;
694211e25f0dSDavid C Somayajulu 	int				rc;
694311e25f0dSDavid C Somayajulu 
694411e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
694511e25f0dSDavid C Somayajulu 
694611e25f0dSDavid C Somayajulu 	bzero(&ucast, sizeof(struct ecore_filter_ucast));
694711e25f0dSDavid C Somayajulu 
694811e25f0dSDavid C Somayajulu         ucast.opcode = opcode;
694911e25f0dSDavid C Somayajulu         ucast.type = ECORE_FILTER_MAC;
695011e25f0dSDavid C Somayajulu         ucast.is_rx_filter = 1;
695111e25f0dSDavid C Somayajulu         ucast.vport_to_add_to = 0;
695211e25f0dSDavid C Somayajulu         memcpy(&ucast.mac[0], mac, ETH_ALEN);
695311e25f0dSDavid C Somayajulu 
695411e25f0dSDavid C Somayajulu 	rc = ecore_filter_ucast_cmd(cdev, &ucast, ECORE_SPQ_MODE_CB, NULL);
695511e25f0dSDavid C Somayajulu 
695611e25f0dSDavid C Somayajulu         return (rc);
695711e25f0dSDavid C Somayajulu }
695811e25f0dSDavid C Somayajulu 
695911e25f0dSDavid C Somayajulu static int
qlnx_remove_all_ucast_mac(qlnx_host_t * ha)696011e25f0dSDavid C Somayajulu qlnx_remove_all_ucast_mac(qlnx_host_t *ha)
696111e25f0dSDavid C Somayajulu {
696211e25f0dSDavid C Somayajulu 	struct ecore_filter_ucast	ucast;
696311e25f0dSDavid C Somayajulu 	struct ecore_dev		*cdev;
696411e25f0dSDavid C Somayajulu 	int				rc;
696511e25f0dSDavid C Somayajulu 
696611e25f0dSDavid C Somayajulu 	bzero(&ucast, sizeof(struct ecore_filter_ucast));
696711e25f0dSDavid C Somayajulu 
696811e25f0dSDavid C Somayajulu 	ucast.opcode = ECORE_FILTER_REPLACE;
696911e25f0dSDavid C Somayajulu 	ucast.type = ECORE_FILTER_MAC;
697011e25f0dSDavid C Somayajulu 	ucast.is_rx_filter = 1;
697111e25f0dSDavid C Somayajulu 
697211e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
697311e25f0dSDavid C Somayajulu 
697411e25f0dSDavid C Somayajulu 	rc = ecore_filter_ucast_cmd(cdev, &ucast, ECORE_SPQ_MODE_CB, NULL);
697511e25f0dSDavid C Somayajulu 
697611e25f0dSDavid C Somayajulu 	return (rc);
697711e25f0dSDavid C Somayajulu }
697811e25f0dSDavid C Somayajulu 
697911e25f0dSDavid C Somayajulu static int
qlnx_remove_all_mcast_mac(qlnx_host_t * ha)698011e25f0dSDavid C Somayajulu qlnx_remove_all_mcast_mac(qlnx_host_t *ha)
698111e25f0dSDavid C Somayajulu {
698211e25f0dSDavid C Somayajulu 	struct ecore_filter_mcast	*mcast;
698311e25f0dSDavid C Somayajulu 	struct ecore_dev		*cdev;
698411e25f0dSDavid C Somayajulu 	int				rc, i;
698511e25f0dSDavid C Somayajulu 
698611e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
698711e25f0dSDavid C Somayajulu 
698811e25f0dSDavid C Somayajulu 	mcast = &ha->ecore_mcast;
698911e25f0dSDavid C Somayajulu 	bzero(mcast, sizeof(struct ecore_filter_mcast));
699011e25f0dSDavid C Somayajulu 
699111e25f0dSDavid C Somayajulu 	mcast->opcode = ECORE_FILTER_REMOVE;
699211e25f0dSDavid C Somayajulu 
699311e25f0dSDavid C Somayajulu 	for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) {
699411e25f0dSDavid C Somayajulu 		if (ha->mcast[i].addr[0] || ha->mcast[i].addr[1] ||
699511e25f0dSDavid C Somayajulu 			ha->mcast[i].addr[2] || ha->mcast[i].addr[3] ||
699611e25f0dSDavid C Somayajulu 			ha->mcast[i].addr[4] || ha->mcast[i].addr[5]) {
6997217ec208SDavid C Somayajulu 			memcpy(&mcast->mac[i][0], &ha->mcast[i].addr[0], ETH_ALEN);
699811e25f0dSDavid C Somayajulu 			mcast->num_mc_addrs++;
699911e25f0dSDavid C Somayajulu 		}
700011e25f0dSDavid C Somayajulu 	}
700111e25f0dSDavid C Somayajulu 	mcast = &ha->ecore_mcast;
700211e25f0dSDavid C Somayajulu 
700311e25f0dSDavid C Somayajulu 	rc = ecore_filter_mcast_cmd(cdev, mcast, ECORE_SPQ_MODE_CB, NULL);
700411e25f0dSDavid C Somayajulu 
700511e25f0dSDavid C Somayajulu 	bzero(ha->mcast, (sizeof(qlnx_mcast_t) * QLNX_MAX_NUM_MULTICAST_ADDRS));
700611e25f0dSDavid C Somayajulu 	ha->nmcast = 0;
700711e25f0dSDavid C Somayajulu 
700811e25f0dSDavid C Somayajulu 	return (rc);
700911e25f0dSDavid C Somayajulu }
701011e25f0dSDavid C Somayajulu 
701111e25f0dSDavid C Somayajulu static int
qlnx_clean_filters(qlnx_host_t * ha)701211e25f0dSDavid C Somayajulu qlnx_clean_filters(qlnx_host_t *ha)
701311e25f0dSDavid C Somayajulu {
701411e25f0dSDavid C Somayajulu         int	rc = 0;
701511e25f0dSDavid C Somayajulu 
701611e25f0dSDavid C Somayajulu 	/* Remove all unicast macs */
701754064a2fSDavid C Somayajulu 	rc = qlnx_remove_all_ucast_mac(ha);
701811e25f0dSDavid C Somayajulu 	if (rc)
701911e25f0dSDavid C Somayajulu 		return rc;
702011e25f0dSDavid C Somayajulu 
702111e25f0dSDavid C Somayajulu 	/* Remove all multicast macs */
702211e25f0dSDavid C Somayajulu 	rc = qlnx_remove_all_mcast_mac(ha);
702311e25f0dSDavid C Somayajulu 	if (rc)
702411e25f0dSDavid C Somayajulu 		return rc;
702511e25f0dSDavid C Somayajulu 
702611e25f0dSDavid C Somayajulu         rc = qlnx_set_ucast_rx_mac(ha, ECORE_FILTER_FLUSH, ha->primary_mac);
702711e25f0dSDavid C Somayajulu 
702811e25f0dSDavid C Somayajulu         return (rc);
702911e25f0dSDavid C Somayajulu }
703011e25f0dSDavid C Somayajulu 
703111e25f0dSDavid C Somayajulu static int
qlnx_set_rx_accept_filter(qlnx_host_t * ha,uint8_t filter)703211e25f0dSDavid C Somayajulu qlnx_set_rx_accept_filter(qlnx_host_t *ha, uint8_t filter)
703311e25f0dSDavid C Somayajulu {
703411e25f0dSDavid C Somayajulu 	struct ecore_filter_accept_flags	accept;
703511e25f0dSDavid C Somayajulu 	int					rc = 0;
703611e25f0dSDavid C Somayajulu 	struct ecore_dev			*cdev;
703711e25f0dSDavid C Somayajulu 
703811e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
703911e25f0dSDavid C Somayajulu 
704011e25f0dSDavid C Somayajulu 	bzero(&accept, sizeof(struct ecore_filter_accept_flags));
704111e25f0dSDavid C Somayajulu 
704211e25f0dSDavid C Somayajulu 	accept.update_rx_mode_config = 1;
704311e25f0dSDavid C Somayajulu 	accept.rx_accept_filter = filter;
704411e25f0dSDavid C Somayajulu 
704511e25f0dSDavid C Somayajulu 	accept.update_tx_mode_config = 1;
704611e25f0dSDavid C Somayajulu 	accept.tx_accept_filter = ECORE_ACCEPT_UCAST_MATCHED |
704711e25f0dSDavid C Somayajulu 		ECORE_ACCEPT_MCAST_MATCHED | ECORE_ACCEPT_BCAST;
704811e25f0dSDavid C Somayajulu 
704911e25f0dSDavid C Somayajulu 	rc = ecore_filter_accept_cmd(cdev, 0, accept, false, false,
705011e25f0dSDavid C Somayajulu 			ECORE_SPQ_MODE_CB, NULL);
705111e25f0dSDavid C Somayajulu 
705211e25f0dSDavid C Somayajulu 	return (rc);
705311e25f0dSDavid C Somayajulu }
705411e25f0dSDavid C Somayajulu 
705511e25f0dSDavid C Somayajulu static int
qlnx_set_rx_mode(qlnx_host_t * ha)705611e25f0dSDavid C Somayajulu qlnx_set_rx_mode(qlnx_host_t *ha)
705711e25f0dSDavid C Somayajulu {
705811e25f0dSDavid C Somayajulu 	int	rc = 0;
705911e25f0dSDavid C Somayajulu 	uint8_t	filter;
7060*1eaecc21SJustin Hibbits 	const if_t ifp = ha->ifp;
7061*1eaecc21SJustin Hibbits 	const struct ifaddr *ifa;
7062792226e5SKeith Reynolds 	struct sockaddr_dl *sdl;
706311e25f0dSDavid C Somayajulu 
7064*1eaecc21SJustin Hibbits 	ifa = if_getifaddr(ifp);
7065*1eaecc21SJustin Hibbits 	if (if_gettype(ifp) == IFT_ETHER && ifa != NULL &&
7066*1eaecc21SJustin Hibbits 			ifa->ifa_addr != NULL) {
7067*1eaecc21SJustin Hibbits 		sdl = (struct sockaddr_dl *) ifa->ifa_addr;
7068792226e5SKeith Reynolds 
7069792226e5SKeith Reynolds 		rc = qlnx_set_ucast_rx_mac(ha, ECORE_FILTER_REPLACE, LLADDR(sdl));
7070792226e5SKeith Reynolds 	} else {
707111e25f0dSDavid C Somayajulu 		rc = qlnx_set_ucast_rx_mac(ha, ECORE_FILTER_REPLACE, ha->primary_mac);
7072792226e5SKeith Reynolds 	}
707311e25f0dSDavid C Somayajulu         if (rc)
707411e25f0dSDavid C Somayajulu                 return rc;
707511e25f0dSDavid C Somayajulu 
707611e25f0dSDavid C Somayajulu 	rc = qlnx_remove_all_mcast_mac(ha);
707711e25f0dSDavid C Somayajulu         if (rc)
707811e25f0dSDavid C Somayajulu                 return rc;
707911e25f0dSDavid C Somayajulu 
708011e25f0dSDavid C Somayajulu 	filter = ECORE_ACCEPT_UCAST_MATCHED |
708111e25f0dSDavid C Somayajulu 			ECORE_ACCEPT_MCAST_MATCHED |
708211e25f0dSDavid C Somayajulu 			ECORE_ACCEPT_BCAST;
7083217ec208SDavid C Somayajulu 
7084*1eaecc21SJustin Hibbits 	if (qlnx_vf_device(ha) == 0 || (if_getflags(ha->ifp) & IFF_PROMISC)) {
7085217ec208SDavid C Somayajulu 		filter |= ECORE_ACCEPT_UCAST_UNMATCHED;
7086217ec208SDavid C Somayajulu 		filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
7087*1eaecc21SJustin Hibbits 	} else if (if_getflags(ha->ifp) & IFF_ALLMULTI) {
7088e3ec564eSKeith Reynolds 		filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
7089217ec208SDavid C Somayajulu 	}
709011e25f0dSDavid C Somayajulu 	ha->filter = filter;
709111e25f0dSDavid C Somayajulu 
709211e25f0dSDavid C Somayajulu 	rc = qlnx_set_rx_accept_filter(ha, filter);
709311e25f0dSDavid C Somayajulu 
709411e25f0dSDavid C Somayajulu 	return (rc);
709511e25f0dSDavid C Somayajulu }
709611e25f0dSDavid C Somayajulu 
709711e25f0dSDavid C Somayajulu static int
qlnx_set_link(qlnx_host_t * ha,bool link_up)709811e25f0dSDavid C Somayajulu qlnx_set_link(qlnx_host_t *ha, bool link_up)
709911e25f0dSDavid C Somayajulu {
710011e25f0dSDavid C Somayajulu         int			i, rc = 0;
710111e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
710211e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*hwfn;
710311e25f0dSDavid C Somayajulu 	struct ecore_ptt	*ptt;
710411e25f0dSDavid C Somayajulu 
7105217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
7106217ec208SDavid C Somayajulu 		return (0);
7107217ec208SDavid C Somayajulu 
710811e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
710911e25f0dSDavid C Somayajulu 
711011e25f0dSDavid C Somayajulu         for_each_hwfn(cdev, i) {
711111e25f0dSDavid C Somayajulu                 hwfn = &cdev->hwfns[i];
711211e25f0dSDavid C Somayajulu 
711311e25f0dSDavid C Somayajulu                 ptt = ecore_ptt_acquire(hwfn);
711411e25f0dSDavid C Somayajulu        	        if (!ptt)
711511e25f0dSDavid C Somayajulu                         return -EBUSY;
711611e25f0dSDavid C Somayajulu 
711711e25f0dSDavid C Somayajulu                 rc = ecore_mcp_set_link(hwfn, ptt, link_up);
711811e25f0dSDavid C Somayajulu 
711911e25f0dSDavid C Somayajulu                 ecore_ptt_release(hwfn, ptt);
712011e25f0dSDavid C Somayajulu 
712111e25f0dSDavid C Somayajulu                 if (rc)
712211e25f0dSDavid C Somayajulu                         return rc;
712311e25f0dSDavid C Somayajulu         }
712411e25f0dSDavid C Somayajulu         return (rc);
712511e25f0dSDavid C Somayajulu }
712611e25f0dSDavid C Somayajulu 
712711e25f0dSDavid C Somayajulu static uint64_t
qlnx_get_counter(if_t ifp,ift_counter cnt)712811e25f0dSDavid C Somayajulu qlnx_get_counter(if_t ifp, ift_counter cnt)
712911e25f0dSDavid C Somayajulu {
713011e25f0dSDavid C Somayajulu 	qlnx_host_t *ha;
713111e25f0dSDavid C Somayajulu 	uint64_t count;
713211e25f0dSDavid C Somayajulu 
713311e25f0dSDavid C Somayajulu         ha = (qlnx_host_t *)if_getsoftc(ifp);
713411e25f0dSDavid C Somayajulu 
713511e25f0dSDavid C Somayajulu         switch (cnt) {
713611e25f0dSDavid C Somayajulu         case IFCOUNTER_IPACKETS:
713711e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.rx_ucast_pkts +
713811e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_mcast_pkts +
713911e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_bcast_pkts;
714011e25f0dSDavid C Somayajulu 		break;
714111e25f0dSDavid C Somayajulu 
714211e25f0dSDavid C Somayajulu         case IFCOUNTER_IERRORS:
714311e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.rx_crc_errors +
714411e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_align_errors +
714511e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_oversize_packets +
714611e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_undersize_packets;
714711e25f0dSDavid C Somayajulu 		break;
714811e25f0dSDavid C Somayajulu 
714911e25f0dSDavid C Somayajulu         case IFCOUNTER_OPACKETS:
715011e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.tx_ucast_pkts +
715111e25f0dSDavid C Somayajulu 			ha->hw_stats.common.tx_mcast_pkts +
715211e25f0dSDavid C Somayajulu 			ha->hw_stats.common.tx_bcast_pkts;
715311e25f0dSDavid C Somayajulu 		break;
715411e25f0dSDavid C Somayajulu 
715511e25f0dSDavid C Somayajulu         case IFCOUNTER_OERRORS:
715611e25f0dSDavid C Somayajulu                 count = ha->hw_stats.common.tx_err_drop_pkts;
715711e25f0dSDavid C Somayajulu 		break;
715811e25f0dSDavid C Somayajulu 
715911e25f0dSDavid C Somayajulu         case IFCOUNTER_COLLISIONS:
716011e25f0dSDavid C Somayajulu                 return (0);
716111e25f0dSDavid C Somayajulu 
716211e25f0dSDavid C Somayajulu         case IFCOUNTER_IBYTES:
716311e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.rx_ucast_bytes +
716411e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_mcast_bytes +
716511e25f0dSDavid C Somayajulu 			ha->hw_stats.common.rx_bcast_bytes;
716611e25f0dSDavid C Somayajulu 		break;
716711e25f0dSDavid C Somayajulu 
716811e25f0dSDavid C Somayajulu         case IFCOUNTER_OBYTES:
716911e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.tx_ucast_bytes +
717011e25f0dSDavid C Somayajulu 			ha->hw_stats.common.tx_mcast_bytes +
717111e25f0dSDavid C Somayajulu 			ha->hw_stats.common.tx_bcast_bytes;
717211e25f0dSDavid C Somayajulu 		break;
717311e25f0dSDavid C Somayajulu 
717411e25f0dSDavid C Somayajulu         case IFCOUNTER_IMCASTS:
717511e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.rx_mcast_bytes;
717611e25f0dSDavid C Somayajulu 		break;
717711e25f0dSDavid C Somayajulu 
717811e25f0dSDavid C Somayajulu         case IFCOUNTER_OMCASTS:
717911e25f0dSDavid C Somayajulu 		count = ha->hw_stats.common.tx_mcast_bytes;
718011e25f0dSDavid C Somayajulu 		break;
718111e25f0dSDavid C Somayajulu 
718211e25f0dSDavid C Somayajulu         case IFCOUNTER_IQDROPS:
718311e25f0dSDavid C Somayajulu         case IFCOUNTER_OQDROPS:
718411e25f0dSDavid C Somayajulu         case IFCOUNTER_NOPROTO:
718511e25f0dSDavid C Somayajulu 
718611e25f0dSDavid C Somayajulu         default:
718711e25f0dSDavid C Somayajulu                 return (if_get_counter_default(ifp, cnt));
718811e25f0dSDavid C Somayajulu         }
718911e25f0dSDavid C Somayajulu 	return (count);
719011e25f0dSDavid C Somayajulu }
719111e25f0dSDavid C Somayajulu 
719211e25f0dSDavid C Somayajulu static void
qlnx_timer(void * arg)719311e25f0dSDavid C Somayajulu qlnx_timer(void *arg)
719411e25f0dSDavid C Somayajulu {
719511e25f0dSDavid C Somayajulu 	qlnx_host_t	*ha;
719611e25f0dSDavid C Somayajulu 
719711e25f0dSDavid C Somayajulu 	ha = (qlnx_host_t *)arg;
719811e25f0dSDavid C Somayajulu 
7199217ec208SDavid C Somayajulu 	if (ha->error_recovery) {
7200217ec208SDavid C Somayajulu 		ha->error_recovery = 0;
7201217ec208SDavid C Somayajulu 		taskqueue_enqueue(ha->err_taskqueue, &ha->err_task);
7202217ec208SDavid C Somayajulu 		return;
7203217ec208SDavid C Somayajulu 	}
7204217ec208SDavid C Somayajulu 
720511e25f0dSDavid C Somayajulu        	ecore_get_vport_stats(&ha->cdev, &ha->hw_stats);
720611e25f0dSDavid C Somayajulu 
720745f13123SDavid C Somayajulu 	if (ha->storm_stats_gather)
720811e25f0dSDavid C Somayajulu 		qlnx_sample_storm_stats(ha);
720911e25f0dSDavid C Somayajulu 
721011e25f0dSDavid C Somayajulu 	callout_reset(&ha->qlnx_callout, hz, qlnx_timer, ha);
721111e25f0dSDavid C Somayajulu 
721211e25f0dSDavid C Somayajulu 	return;
721311e25f0dSDavid C Somayajulu }
721411e25f0dSDavid C Somayajulu 
721511e25f0dSDavid C Somayajulu static int
qlnx_load(qlnx_host_t * ha)721611e25f0dSDavid C Somayajulu qlnx_load(qlnx_host_t *ha)
721711e25f0dSDavid C Somayajulu {
721811e25f0dSDavid C Somayajulu 	int			i;
721911e25f0dSDavid C Somayajulu 	int			rc = 0;
722011e25f0dSDavid C Somayajulu         device_t		dev;
722111e25f0dSDavid C Somayajulu 
722211e25f0dSDavid C Somayajulu         dev = ha->pci_dev;
722311e25f0dSDavid C Somayajulu 
72247a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
722511e25f0dSDavid C Somayajulu 
722611e25f0dSDavid C Somayajulu         rc = qlnx_alloc_mem_arrays(ha);
722711e25f0dSDavid C Somayajulu         if (rc)
722811e25f0dSDavid C Somayajulu                 goto qlnx_load_exit0;
722911e25f0dSDavid C Somayajulu 
723011e25f0dSDavid C Somayajulu         qlnx_init_fp(ha);
723111e25f0dSDavid C Somayajulu 
723211e25f0dSDavid C Somayajulu         rc = qlnx_alloc_mem_load(ha);
723311e25f0dSDavid C Somayajulu         if (rc)
723411e25f0dSDavid C Somayajulu                 goto qlnx_load_exit1;
723511e25f0dSDavid C Somayajulu 
72367a377fbeSDavid C Somayajulu         QL_DPRINT2(ha, "Allocated %d RSS queues on %d TC/s\n",
72377a377fbeSDavid C Somayajulu 		   ha->num_rss, ha->num_tc);
723811e25f0dSDavid C Somayajulu 
723911e25f0dSDavid C Somayajulu 	for (i = 0; i < ha->num_rss; i++) {
724011e25f0dSDavid C Somayajulu 		if ((rc = bus_setup_intr(dev, ha->irq_vec[i].irq,
724111e25f0dSDavid C Somayajulu                         (INTR_TYPE_NET | INTR_MPSAFE),
724211e25f0dSDavid C Somayajulu                         NULL, qlnx_fp_isr, &ha->irq_vec[i],
724311e25f0dSDavid C Somayajulu                         &ha->irq_vec[i].handle))) {
72447a377fbeSDavid C Somayajulu                         QL_DPRINT1(ha, "could not setup interrupt\n");
724511e25f0dSDavid C Somayajulu                         goto qlnx_load_exit2;
724611e25f0dSDavid C Somayajulu 		}
724711e25f0dSDavid C Somayajulu 
72487a377fbeSDavid C Somayajulu 		QL_DPRINT2(ha, "rss_id = %d irq_rid %d \
72497a377fbeSDavid C Somayajulu 			 irq %p handle %p\n", i,
725011e25f0dSDavid C Somayajulu 			ha->irq_vec[i].irq_rid,
72517a377fbeSDavid C Somayajulu 			ha->irq_vec[i].irq, ha->irq_vec[i].handle);
725211e25f0dSDavid C Somayajulu 
725311e25f0dSDavid C Somayajulu 		bus_bind_intr(dev, ha->irq_vec[i].irq, (i % mp_ncpus));
725411e25f0dSDavid C Somayajulu 	}
725511e25f0dSDavid C Somayajulu 
725611e25f0dSDavid C Somayajulu         rc = qlnx_start_queues(ha);
725711e25f0dSDavid C Somayajulu         if (rc)
725811e25f0dSDavid C Somayajulu                 goto qlnx_load_exit2;
725911e25f0dSDavid C Somayajulu 
72607a377fbeSDavid C Somayajulu         QL_DPRINT2(ha, "Start VPORT, RXQ and TXQ succeeded\n");
726111e25f0dSDavid C Somayajulu 
726211e25f0dSDavid C Somayajulu         /* Add primary mac and set Rx filters */
726311e25f0dSDavid C Somayajulu         rc = qlnx_set_rx_mode(ha);
726411e25f0dSDavid C Somayajulu         if (rc)
726511e25f0dSDavid C Somayajulu                 goto qlnx_load_exit2;
726611e25f0dSDavid C Somayajulu 
726711e25f0dSDavid C Somayajulu         /* Ask for link-up using current configuration */
726811e25f0dSDavid C Somayajulu 	qlnx_set_link(ha, true);
726911e25f0dSDavid C Somayajulu 
7270217ec208SDavid C Somayajulu 	if (qlnx_vf_device(ha) == 0)
7271217ec208SDavid C Somayajulu 		qlnx_link_update(&ha->cdev.hwfns[0]);
7272217ec208SDavid C Somayajulu 
727311e25f0dSDavid C Somayajulu         ha->state = QLNX_STATE_OPEN;
727411e25f0dSDavid C Somayajulu 
727511e25f0dSDavid C Somayajulu 	bzero(&ha->hw_stats, sizeof(struct ecore_eth_stats));
727611e25f0dSDavid C Somayajulu 
727711e25f0dSDavid C Somayajulu 	if (ha->flags.callout_init)
727811e25f0dSDavid C Somayajulu         	callout_reset(&ha->qlnx_callout, hz, qlnx_timer, ha);
727911e25f0dSDavid C Somayajulu 
728011e25f0dSDavid C Somayajulu         goto qlnx_load_exit0;
728111e25f0dSDavid C Somayajulu 
728211e25f0dSDavid C Somayajulu qlnx_load_exit2:
728311e25f0dSDavid C Somayajulu         qlnx_free_mem_load(ha);
728411e25f0dSDavid C Somayajulu 
728511e25f0dSDavid C Somayajulu qlnx_load_exit1:
728611e25f0dSDavid C Somayajulu         ha->num_rss = 0;
728711e25f0dSDavid C Somayajulu 
728811e25f0dSDavid C Somayajulu qlnx_load_exit0:
72897a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit [%d]\n", rc);
729011e25f0dSDavid C Somayajulu         return rc;
729111e25f0dSDavid C Somayajulu }
729211e25f0dSDavid C Somayajulu 
729311e25f0dSDavid C Somayajulu static void
qlnx_drain_soft_lro(qlnx_host_t * ha)729411e25f0dSDavid C Somayajulu qlnx_drain_soft_lro(qlnx_host_t *ha)
729511e25f0dSDavid C Somayajulu {
729611e25f0dSDavid C Somayajulu #ifdef QLNX_SOFT_LRO
729711e25f0dSDavid C Somayajulu 
7298727bfe38SJustin Hibbits 	if_t		ifp;
729911e25f0dSDavid C Somayajulu 	int		i;
730011e25f0dSDavid C Somayajulu 
730111e25f0dSDavid C Somayajulu 	ifp = ha->ifp;
730211e25f0dSDavid C Somayajulu 
7303727bfe38SJustin Hibbits 	if (if_getcapenable(ifp) & IFCAP_LRO) {
730411e25f0dSDavid C Somayajulu 	        for (i = 0; i < ha->num_rss; i++) {
730511e25f0dSDavid C Somayajulu 			struct qlnx_fastpath *fp = &ha->fp_array[i];
730611e25f0dSDavid C Somayajulu 			struct lro_ctrl *lro;
730711e25f0dSDavid C Somayajulu 
730811e25f0dSDavid C Somayajulu 			lro = &fp->rxq->lro;
730911e25f0dSDavid C Somayajulu 
731011e25f0dSDavid C Somayajulu 			tcp_lro_flush_all(lro);
731111e25f0dSDavid C Somayajulu                 }
731211e25f0dSDavid C Somayajulu 	}
731311e25f0dSDavid C Somayajulu 
731411e25f0dSDavid C Somayajulu #endif /* #ifdef QLNX_SOFT_LRO */
731511e25f0dSDavid C Somayajulu 
731611e25f0dSDavid C Somayajulu 	return;
731711e25f0dSDavid C Somayajulu }
731811e25f0dSDavid C Somayajulu 
731911e25f0dSDavid C Somayajulu static void
qlnx_unload(qlnx_host_t * ha)732011e25f0dSDavid C Somayajulu qlnx_unload(qlnx_host_t *ha)
732111e25f0dSDavid C Somayajulu {
732211e25f0dSDavid C Somayajulu 	struct ecore_dev	*cdev;
732311e25f0dSDavid C Somayajulu         device_t		dev;
732411e25f0dSDavid C Somayajulu 	int			i;
732511e25f0dSDavid C Somayajulu 
732611e25f0dSDavid C Somayajulu 	cdev = &ha->cdev;
732711e25f0dSDavid C Somayajulu         dev = ha->pci_dev;
732811e25f0dSDavid C Somayajulu 
73297a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "enter\n");
73307a377fbeSDavid C Somayajulu         QL_DPRINT1(ha, " QLNX STATE = %d\n",ha->state);
733111e25f0dSDavid C Somayajulu 
733211e25f0dSDavid C Somayajulu 	if (ha->state == QLNX_STATE_OPEN) {
733311e25f0dSDavid C Somayajulu 		qlnx_set_link(ha, false);
733411e25f0dSDavid C Somayajulu 		qlnx_clean_filters(ha);
733511e25f0dSDavid C Somayajulu 		qlnx_stop_queues(ha);
733611e25f0dSDavid C Somayajulu 		ecore_hw_stop_fastpath(cdev);
733711e25f0dSDavid C Somayajulu 
733811e25f0dSDavid C Somayajulu 		for (i = 0; i < ha->num_rss; i++) {
733911e25f0dSDavid C Somayajulu 			if (ha->irq_vec[i].handle) {
734011e25f0dSDavid C Somayajulu 				(void)bus_teardown_intr(dev,
734111e25f0dSDavid C Somayajulu 					ha->irq_vec[i].irq,
734211e25f0dSDavid C Somayajulu 					ha->irq_vec[i].handle);
734311e25f0dSDavid C Somayajulu 				ha->irq_vec[i].handle = NULL;
734411e25f0dSDavid C Somayajulu 			}
734511e25f0dSDavid C Somayajulu 		}
734611e25f0dSDavid C Somayajulu 
734711e25f0dSDavid C Somayajulu 		qlnx_drain_fp_taskqueues(ha);
734811e25f0dSDavid C Somayajulu 		qlnx_drain_soft_lro(ha);
734911e25f0dSDavid C Somayajulu         	qlnx_free_mem_load(ha);
735011e25f0dSDavid C Somayajulu 	}
735111e25f0dSDavid C Somayajulu 
735211e25f0dSDavid C Somayajulu 	if (ha->flags.callout_init)
735311e25f0dSDavid C Somayajulu 		callout_drain(&ha->qlnx_callout);
735411e25f0dSDavid C Somayajulu 
735511e25f0dSDavid C Somayajulu 	qlnx_mdelay(__func__, 1000);
735611e25f0dSDavid C Somayajulu 
735711e25f0dSDavid C Somayajulu         ha->state = QLNX_STATE_CLOSED;
735811e25f0dSDavid C Somayajulu 
73597a377fbeSDavid C Somayajulu 	QL_DPRINT2(ha, "exit\n");
736011e25f0dSDavid C Somayajulu 	return;
736111e25f0dSDavid C Somayajulu }
736211e25f0dSDavid C Somayajulu 
736311e25f0dSDavid C Somayajulu static int
qlnx_grc_dumpsize(qlnx_host_t * ha,uint32_t * num_dwords,int hwfn_index)736411e25f0dSDavid C Somayajulu qlnx_grc_dumpsize(qlnx_host_t *ha, uint32_t *num_dwords, int hwfn_index)
736511e25f0dSDavid C Somayajulu {
736611e25f0dSDavid C Somayajulu 	int			rval = -1;
736711e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
736811e25f0dSDavid C Somayajulu 	struct ecore_ptt	*p_ptt;
736911e25f0dSDavid C Somayajulu 
737011e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
737111e25f0dSDavid C Somayajulu 
737211e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[hwfn_index];
737311e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
737411e25f0dSDavid C Somayajulu 
737511e25f0dSDavid C Somayajulu         if (!p_ptt) {
73767a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "ecore_ptt_acquire failed\n");
737711e25f0dSDavid C Somayajulu                 return (rval);
737811e25f0dSDavid C Somayajulu         }
737911e25f0dSDavid C Somayajulu 
738011e25f0dSDavid C Somayajulu         rval = ecore_dbg_grc_get_dump_buf_size(p_hwfn, p_ptt, num_dwords);
738111e25f0dSDavid C Somayajulu 
738211e25f0dSDavid C Somayajulu 	if (rval == DBG_STATUS_OK)
738311e25f0dSDavid C Somayajulu                 rval = 0;
738411e25f0dSDavid C Somayajulu         else {
73857a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "ecore_dbg_grc_get_dump_buf_size failed"
73867a377fbeSDavid C Somayajulu 			"[0x%x]\n", rval);
738711e25f0dSDavid C Somayajulu 	}
738811e25f0dSDavid C Somayajulu 
738911e25f0dSDavid C Somayajulu         ecore_ptt_release(p_hwfn, p_ptt);
739011e25f0dSDavid C Somayajulu 
739111e25f0dSDavid C Somayajulu         return (rval);
739211e25f0dSDavid C Somayajulu }
739311e25f0dSDavid C Somayajulu 
739411e25f0dSDavid C Somayajulu static int
qlnx_idle_chk_size(qlnx_host_t * ha,uint32_t * num_dwords,int hwfn_index)739511e25f0dSDavid C Somayajulu qlnx_idle_chk_size(qlnx_host_t *ha, uint32_t *num_dwords, int hwfn_index)
739611e25f0dSDavid C Somayajulu {
739711e25f0dSDavid C Somayajulu 	int			rval = -1;
739811e25f0dSDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
739911e25f0dSDavid C Somayajulu 	struct ecore_ptt	*p_ptt;
740011e25f0dSDavid C Somayajulu 
740111e25f0dSDavid C Somayajulu 	ecore_dbg_set_app_ver(ecore_dbg_get_fw_func_ver());
740211e25f0dSDavid C Somayajulu 
740311e25f0dSDavid C Somayajulu 	p_hwfn = &ha->cdev.hwfns[hwfn_index];
740411e25f0dSDavid C Somayajulu 	p_ptt = ecore_ptt_acquire(p_hwfn);
740511e25f0dSDavid C Somayajulu 
740611e25f0dSDavid C Somayajulu         if (!p_ptt) {
74077a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "ecore_ptt_acquire failed\n");
740811e25f0dSDavid C Somayajulu                 return (rval);
740911e25f0dSDavid C Somayajulu         }
741011e25f0dSDavid C Somayajulu 
741111e25f0dSDavid C Somayajulu         rval = ecore_dbg_idle_chk_get_dump_buf_size(p_hwfn, p_ptt, num_dwords);
741211e25f0dSDavid C Somayajulu 
741311e25f0dSDavid C Somayajulu 	if (rval == DBG_STATUS_OK)
741411e25f0dSDavid C Somayajulu                 rval = 0;
741511e25f0dSDavid C Somayajulu         else {
74167a377fbeSDavid C Somayajulu 		QL_DPRINT1(ha, "ecore_dbg_idle_chk_get_dump_buf_size failed"
74177a377fbeSDavid C Somayajulu 			" [0x%x]\n", rval);
741811e25f0dSDavid C Somayajulu 	}
741911e25f0dSDavid C Somayajulu 
742011e25f0dSDavid C Somayajulu         ecore_ptt_release(p_hwfn, p_ptt);
742111e25f0dSDavid C Somayajulu 
742211e25f0dSDavid C Somayajulu         return (rval);
742311e25f0dSDavid C Somayajulu }
742411e25f0dSDavid C Somayajulu 
742511e25f0dSDavid C Somayajulu static void
qlnx_sample_storm_stats(qlnx_host_t * ha)742611e25f0dSDavid C Somayajulu qlnx_sample_storm_stats(qlnx_host_t *ha)
742711e25f0dSDavid C Somayajulu {
742811e25f0dSDavid C Somayajulu         int			i, index;
742911e25f0dSDavid C Somayajulu         struct ecore_dev	*cdev;
743011e25f0dSDavid C Somayajulu 	qlnx_storm_stats_t	*s_stats;
743111e25f0dSDavid C Somayajulu 	uint32_t		reg;
743211e25f0dSDavid C Somayajulu         struct ecore_ptt	*p_ptt;
743311e25f0dSDavid C Somayajulu         struct ecore_hwfn	*hwfn;
743411e25f0dSDavid C Somayajulu 
743511e25f0dSDavid C Somayajulu 	if (ha->storm_stats_index >= QLNX_STORM_STATS_SAMPLES_PER_HWFN) {
743645f13123SDavid C Somayajulu 		ha->storm_stats_gather = 0;
743711e25f0dSDavid C Somayajulu 		return;
743811e25f0dSDavid C Somayajulu 	}
743911e25f0dSDavid C Somayajulu 
744011e25f0dSDavid C Somayajulu         cdev = &ha->cdev;
744111e25f0dSDavid C Somayajulu 
744211e25f0dSDavid C Somayajulu         for_each_hwfn(cdev, i) {
744311e25f0dSDavid C Somayajulu                 hwfn = &cdev->hwfns[i];
744411e25f0dSDavid C Somayajulu 
744511e25f0dSDavid C Somayajulu                 p_ptt = ecore_ptt_acquire(hwfn);
744611e25f0dSDavid C Somayajulu                 if (!p_ptt)
744711e25f0dSDavid C Somayajulu                         return;
744811e25f0dSDavid C Somayajulu 
744911e25f0dSDavid C Somayajulu 		index = ha->storm_stats_index +
745011e25f0dSDavid C Somayajulu 				(i * QLNX_STORM_STATS_SAMPLES_PER_HWFN);
745111e25f0dSDavid C Somayajulu 
745211e25f0dSDavid C Somayajulu 		s_stats = &ha->storm_stats[index];
745311e25f0dSDavid C Somayajulu 
745411e25f0dSDavid C Somayajulu 		/* XSTORM */
745511e25f0dSDavid C Somayajulu 		reg = XSEM_REG_FAST_MEMORY +
745611e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_ACTIVE_CYCLES_BB_K2;
745711e25f0dSDavid C Somayajulu 		s_stats->xstorm_active_cycles = ecore_rd(hwfn, p_ptt, reg);
745811e25f0dSDavid C Somayajulu 
745911e25f0dSDavid C Somayajulu 		reg = XSEM_REG_FAST_MEMORY +
746011e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_STALL_CYCLES_BB_K2;
746111e25f0dSDavid C Somayajulu 		s_stats->xstorm_stall_cycles = ecore_rd(hwfn, p_ptt, reg);
746211e25f0dSDavid C Somayajulu 
746311e25f0dSDavid C Somayajulu 		reg = XSEM_REG_FAST_MEMORY +
746411e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_SLEEPING_CYCLES_BB_K2;
746511e25f0dSDavid C Somayajulu 		s_stats->xstorm_sleeping_cycles = ecore_rd(hwfn, p_ptt, reg);
746611e25f0dSDavid C Somayajulu 
746711e25f0dSDavid C Somayajulu 		reg = XSEM_REG_FAST_MEMORY +
746811e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_INACTIVE_CYCLES_BB_K2;
746911e25f0dSDavid C Somayajulu 		s_stats->xstorm_inactive_cycles = ecore_rd(hwfn, p_ptt, reg);
747011e25f0dSDavid C Somayajulu 
747111e25f0dSDavid C Somayajulu 		/* YSTORM */
747211e25f0dSDavid C Somayajulu 		reg = YSEM_REG_FAST_MEMORY +
747311e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_ACTIVE_CYCLES_BB_K2;
747411e25f0dSDavid C Somayajulu 		s_stats->ystorm_active_cycles = ecore_rd(hwfn, p_ptt, reg);
747511e25f0dSDavid C Somayajulu 
747611e25f0dSDavid C Somayajulu 		reg = YSEM_REG_FAST_MEMORY +
747711e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_STALL_CYCLES_BB_K2;
747811e25f0dSDavid C Somayajulu 		s_stats->ystorm_stall_cycles = ecore_rd(hwfn, p_ptt, reg);
747911e25f0dSDavid C Somayajulu 
748011e25f0dSDavid C Somayajulu 		reg = YSEM_REG_FAST_MEMORY +
748111e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_SLEEPING_CYCLES_BB_K2;
748211e25f0dSDavid C Somayajulu 		s_stats->ystorm_sleeping_cycles = ecore_rd(hwfn, p_ptt, reg);
748311e25f0dSDavid C Somayajulu 
748411e25f0dSDavid C Somayajulu 		reg = YSEM_REG_FAST_MEMORY +
748511e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_INACTIVE_CYCLES_BB_K2;
748611e25f0dSDavid C Somayajulu 		s_stats->ystorm_inactive_cycles = ecore_rd(hwfn, p_ptt, reg);
748711e25f0dSDavid C Somayajulu 
748811e25f0dSDavid C Somayajulu 		/* PSTORM */
748911e25f0dSDavid C Somayajulu 		reg = PSEM_REG_FAST_MEMORY +
749011e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_ACTIVE_CYCLES_BB_K2;
749111e25f0dSDavid C Somayajulu 		s_stats->pstorm_active_cycles = ecore_rd(hwfn, p_ptt, reg);
749211e25f0dSDavid C Somayajulu 
749311e25f0dSDavid C Somayajulu 		reg = PSEM_REG_FAST_MEMORY +
749411e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_STALL_CYCLES_BB_K2;
749511e25f0dSDavid C Somayajulu 		s_stats->pstorm_stall_cycles = ecore_rd(hwfn, p_ptt, reg);
749611e25f0dSDavid C Somayajulu 
749711e25f0dSDavid C Somayajulu 		reg = PSEM_REG_FAST_MEMORY +
749811e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_SLEEPING_CYCLES_BB_K2;
749911e25f0dSDavid C Somayajulu 		s_stats->pstorm_sleeping_cycles = ecore_rd(hwfn, p_ptt, reg);
750011e25f0dSDavid C Somayajulu 
750111e25f0dSDavid C Somayajulu 		reg = PSEM_REG_FAST_MEMORY +
750211e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_INACTIVE_CYCLES_BB_K2;
750311e25f0dSDavid C Somayajulu 		s_stats->pstorm_inactive_cycles = ecore_rd(hwfn, p_ptt, reg);
750411e25f0dSDavid C Somayajulu 
750511e25f0dSDavid C Somayajulu 		/* TSTORM */
750611e25f0dSDavid C Somayajulu 		reg = TSEM_REG_FAST_MEMORY +
750711e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_ACTIVE_CYCLES_BB_K2;
750811e25f0dSDavid C Somayajulu 		s_stats->tstorm_active_cycles = ecore_rd(hwfn, p_ptt, reg);
750911e25f0dSDavid C Somayajulu 
751011e25f0dSDavid C Somayajulu 		reg = TSEM_REG_FAST_MEMORY +
751111e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_STALL_CYCLES_BB_K2;
751211e25f0dSDavid C Somayajulu 		s_stats->tstorm_stall_cycles = ecore_rd(hwfn, p_ptt, reg);
751311e25f0dSDavid C Somayajulu 
751411e25f0dSDavid C Somayajulu 		reg = TSEM_REG_FAST_MEMORY +
751511e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_SLEEPING_CYCLES_BB_K2;
751611e25f0dSDavid C Somayajulu 		s_stats->tstorm_sleeping_cycles = ecore_rd(hwfn, p_ptt, reg);
751711e25f0dSDavid C Somayajulu 
751811e25f0dSDavid C Somayajulu 		reg = TSEM_REG_FAST_MEMORY +
751911e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_INACTIVE_CYCLES_BB_K2;
752011e25f0dSDavid C Somayajulu 		s_stats->tstorm_inactive_cycles = ecore_rd(hwfn, p_ptt, reg);
752111e25f0dSDavid C Somayajulu 
752211e25f0dSDavid C Somayajulu 		/* MSTORM */
752311e25f0dSDavid C Somayajulu 		reg = MSEM_REG_FAST_MEMORY +
752411e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_ACTIVE_CYCLES_BB_K2;
752511e25f0dSDavid C Somayajulu 		s_stats->mstorm_active_cycles = ecore_rd(hwfn, p_ptt, reg);
752611e25f0dSDavid C Somayajulu 
752711e25f0dSDavid C Somayajulu 		reg = MSEM_REG_FAST_MEMORY +
752811e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_STALL_CYCLES_BB_K2;
752911e25f0dSDavid C Somayajulu 		s_stats->mstorm_stall_cycles = ecore_rd(hwfn, p_ptt, reg);
753011e25f0dSDavid C Somayajulu 
753111e25f0dSDavid C Somayajulu 		reg = MSEM_REG_FAST_MEMORY +
753211e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_SLEEPING_CYCLES_BB_K2;
753311e25f0dSDavid C Somayajulu 		s_stats->mstorm_sleeping_cycles = ecore_rd(hwfn, p_ptt, reg);
753411e25f0dSDavid C Somayajulu 
753511e25f0dSDavid C Somayajulu 		reg = MSEM_REG_FAST_MEMORY +
753611e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_INACTIVE_CYCLES_BB_K2;
753711e25f0dSDavid C Somayajulu 		s_stats->mstorm_inactive_cycles = ecore_rd(hwfn, p_ptt, reg);
753811e25f0dSDavid C Somayajulu 
753911e25f0dSDavid C Somayajulu 		/* USTORM */
754011e25f0dSDavid C Somayajulu 		reg = USEM_REG_FAST_MEMORY +
754111e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_ACTIVE_CYCLES_BB_K2;
754211e25f0dSDavid C Somayajulu 		s_stats->ustorm_active_cycles = ecore_rd(hwfn, p_ptt, reg);
754311e25f0dSDavid C Somayajulu 
754411e25f0dSDavid C Somayajulu 		reg = USEM_REG_FAST_MEMORY +
754511e25f0dSDavid C Somayajulu 				SEM_FAST_REG_STORM_STALL_CYCLES_BB_K2;
754611e25f0dSDavid C Somayajulu 		s_stats->ustorm_stall_cycles = ecore_rd(hwfn, p_ptt, reg);
754711e25f0dSDavid C Somayajulu 
754811e25f0dSDavid C Somayajulu 		reg = USEM_REG_FAST_MEMORY +
754911e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_SLEEPING_CYCLES_BB_K2;
755011e25f0dSDavid C Somayajulu 		s_stats->ustorm_sleeping_cycles = ecore_rd(hwfn, p_ptt, reg);
755111e25f0dSDavid C Somayajulu 
755211e25f0dSDavid C Somayajulu 		reg = USEM_REG_FAST_MEMORY +
755311e25f0dSDavid C Somayajulu 				SEM_FAST_REG_IDLE_INACTIVE_CYCLES_BB_K2;
755411e25f0dSDavid C Somayajulu 		s_stats->ustorm_inactive_cycles = ecore_rd(hwfn, p_ptt, reg);
755511e25f0dSDavid C Somayajulu 
755611e25f0dSDavid C Somayajulu                 ecore_ptt_release(hwfn, p_ptt);
755711e25f0dSDavid C Somayajulu         }
755811e25f0dSDavid C Somayajulu 
755911e25f0dSDavid C Somayajulu 	ha->storm_stats_index++;
756011e25f0dSDavid C Somayajulu 
756111e25f0dSDavid C Somayajulu         return;
756211e25f0dSDavid C Somayajulu }
756311e25f0dSDavid C Somayajulu 
756411e25f0dSDavid C Somayajulu /*
756511e25f0dSDavid C Somayajulu  * Name: qlnx_dump_buf8
756611e25f0dSDavid C Somayajulu  * Function: dumps a buffer as bytes
756711e25f0dSDavid C Somayajulu  */
756811e25f0dSDavid C Somayajulu static void
qlnx_dump_buf8(qlnx_host_t * ha,const char * msg,void * dbuf,uint32_t len)756911e25f0dSDavid C Somayajulu qlnx_dump_buf8(qlnx_host_t *ha, const char *msg, void *dbuf, uint32_t len)
757011e25f0dSDavid C Somayajulu {
757111e25f0dSDavid C Somayajulu         device_t	dev;
757211e25f0dSDavid C Somayajulu         uint32_t	i = 0;
757311e25f0dSDavid C Somayajulu         uint8_t		*buf;
757411e25f0dSDavid C Somayajulu 
757511e25f0dSDavid C Somayajulu         dev = ha->pci_dev;
757611e25f0dSDavid C Somayajulu         buf = dbuf;
757711e25f0dSDavid C Somayajulu 
757811e25f0dSDavid C Somayajulu         device_printf(dev, "%s: %s 0x%x dump start\n", __func__, msg, len);
757911e25f0dSDavid C Somayajulu 
758011e25f0dSDavid C Somayajulu         while (len >= 16) {
758111e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
758211e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
758311e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
758411e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3],
758511e25f0dSDavid C Somayajulu                         buf[4], buf[5], buf[6], buf[7],
758611e25f0dSDavid C Somayajulu                         buf[8], buf[9], buf[10], buf[11],
758711e25f0dSDavid C Somayajulu                         buf[12], buf[13], buf[14], buf[15]);
758811e25f0dSDavid C Somayajulu                 i += 16;
758911e25f0dSDavid C Somayajulu                 len -= 16;
759011e25f0dSDavid C Somayajulu                 buf += 16;
759111e25f0dSDavid C Somayajulu         }
759211e25f0dSDavid C Somayajulu         switch (len) {
759311e25f0dSDavid C Somayajulu         case 1:
759411e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x: %02x\n", i, buf[0]);
759511e25f0dSDavid C Somayajulu                 break;
759611e25f0dSDavid C Somayajulu         case 2:
759711e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x: %02x %02x\n", i, buf[0], buf[1]);
759811e25f0dSDavid C Somayajulu                 break;
759911e25f0dSDavid C Somayajulu         case 3:
760011e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x: %02x %02x %02x\n",
760111e25f0dSDavid C Somayajulu                         i, buf[0], buf[1], buf[2]);
760211e25f0dSDavid C Somayajulu                 break;
760311e25f0dSDavid C Somayajulu         case 4:
760411e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x: %02x %02x %02x %02x\n", i,
760511e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3]);
760611e25f0dSDavid C Somayajulu                 break;
760711e25f0dSDavid C Somayajulu         case 5:
760811e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
760911e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x\n", i,
761011e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4]);
761111e25f0dSDavid C Somayajulu                 break;
761211e25f0dSDavid C Somayajulu         case 6:
761311e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
761411e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x\n", i,
761511e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
761611e25f0dSDavid C Somayajulu                 break;
761711e25f0dSDavid C Somayajulu         case 7:
761811e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
761911e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x\n", i,
762011e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
762111e25f0dSDavid C Somayajulu                 break;
762211e25f0dSDavid C Somayajulu         case 8:
762311e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
762411e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
762511e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
762611e25f0dSDavid C Somayajulu                         buf[7]);
762711e25f0dSDavid C Somayajulu                 break;
762811e25f0dSDavid C Somayajulu         case 9:
762911e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
763011e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
763111e25f0dSDavid C Somayajulu                         " %02x\n", i,
763211e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
763311e25f0dSDavid C Somayajulu                         buf[7], buf[8]);
763411e25f0dSDavid C Somayajulu                 break;
763511e25f0dSDavid C Somayajulu         case 10:
763611e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
763711e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
763811e25f0dSDavid C Somayajulu                         " %02x %02x\n", i,
763911e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
764011e25f0dSDavid C Somayajulu                         buf[7], buf[8], buf[9]);
764111e25f0dSDavid C Somayajulu                 break;
764211e25f0dSDavid C Somayajulu         case 11:
764311e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
764411e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
764511e25f0dSDavid C Somayajulu                         " %02x %02x %02x\n", i,
764611e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
764711e25f0dSDavid C Somayajulu                         buf[7], buf[8], buf[9], buf[10]);
764811e25f0dSDavid C Somayajulu                 break;
764911e25f0dSDavid C Somayajulu         case 12:
765011e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
765111e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
765211e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x\n", i,
765311e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
765411e25f0dSDavid C Somayajulu                         buf[7], buf[8], buf[9], buf[10], buf[11]);
765511e25f0dSDavid C Somayajulu                 break;
765611e25f0dSDavid C Somayajulu         case 13:
765711e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
765811e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
765911e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x\n", i,
766011e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
766111e25f0dSDavid C Somayajulu                         buf[7], buf[8], buf[9], buf[10], buf[11], buf[12]);
766211e25f0dSDavid C Somayajulu                 break;
766311e25f0dSDavid C Somayajulu         case 14:
766411e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
766511e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
766611e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x\n", i,
766711e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
766811e25f0dSDavid C Somayajulu                         buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
766911e25f0dSDavid C Somayajulu                         buf[13]);
767011e25f0dSDavid C Somayajulu                 break;
767111e25f0dSDavid C Somayajulu         case 15:
767211e25f0dSDavid C Somayajulu                 device_printf(dev,"0x%08x:"
767311e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x %02x"
767411e25f0dSDavid C Somayajulu                         " %02x %02x %02x %02x %02x %02x %02x\n", i,
767511e25f0dSDavid C Somayajulu                         buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
767611e25f0dSDavid C Somayajulu                         buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
767711e25f0dSDavid C Somayajulu                         buf[13], buf[14]);
767811e25f0dSDavid C Somayajulu                 break;
767911e25f0dSDavid C Somayajulu         default:
768011e25f0dSDavid C Somayajulu                 break;
768111e25f0dSDavid C Somayajulu         }
768211e25f0dSDavid C Somayajulu 
768311e25f0dSDavid C Somayajulu         device_printf(dev, "%s: %s dump end\n", __func__, msg);
768411e25f0dSDavid C Somayajulu 
768511e25f0dSDavid C Somayajulu         return;
768611e25f0dSDavid C Somayajulu }
768711e25f0dSDavid C Somayajulu 
7688217ec208SDavid C Somayajulu #ifdef CONFIG_ECORE_SRIOV
7689217ec208SDavid C Somayajulu 
7690217ec208SDavid C Somayajulu static void
__qlnx_osal_iov_vf_cleanup(struct ecore_hwfn * p_hwfn,uint8_t rel_vf_id)7691217ec208SDavid C Somayajulu __qlnx_osal_iov_vf_cleanup(struct ecore_hwfn *p_hwfn, uint8_t rel_vf_id)
7692217ec208SDavid C Somayajulu {
7693217ec208SDavid C Somayajulu         struct ecore_public_vf_info *vf_info;
7694217ec208SDavid C Somayajulu 
7695217ec208SDavid C Somayajulu         vf_info = ecore_iov_get_public_vf_info(p_hwfn, rel_vf_id, false);
7696217ec208SDavid C Somayajulu 
7697217ec208SDavid C Somayajulu         if (!vf_info)
7698217ec208SDavid C Somayajulu                 return;
7699217ec208SDavid C Somayajulu 
7700217ec208SDavid C Somayajulu         /* Clear the VF mac */
7701217ec208SDavid C Somayajulu         memset(vf_info->forced_mac, 0, ETH_ALEN);
7702217ec208SDavid C Somayajulu 
7703217ec208SDavid C Somayajulu         vf_info->forced_vlan = 0;
7704217ec208SDavid C Somayajulu 
7705217ec208SDavid C Somayajulu 	return;
7706217ec208SDavid C Somayajulu }
7707217ec208SDavid C Somayajulu 
7708217ec208SDavid C Somayajulu void
qlnx_osal_iov_vf_cleanup(void * p_hwfn,uint8_t relative_vf_id)7709217ec208SDavid C Somayajulu qlnx_osal_iov_vf_cleanup(void *p_hwfn, uint8_t relative_vf_id)
7710217ec208SDavid C Somayajulu {
7711217ec208SDavid C Somayajulu 	__qlnx_osal_iov_vf_cleanup(p_hwfn, relative_vf_id);
7712217ec208SDavid C Somayajulu 	return;
7713217ec208SDavid C Somayajulu }
7714217ec208SDavid C Somayajulu 
7715217ec208SDavid C Somayajulu static int
__qlnx_iov_chk_ucast(struct ecore_hwfn * p_hwfn,int vfid,struct ecore_filter_ucast * params)7716217ec208SDavid C Somayajulu __qlnx_iov_chk_ucast(struct ecore_hwfn *p_hwfn, int vfid,
7717217ec208SDavid C Somayajulu 	struct ecore_filter_ucast *params)
7718217ec208SDavid C Somayajulu {
7719217ec208SDavid C Somayajulu         struct ecore_public_vf_info *vf;
7720217ec208SDavid C Somayajulu 
7721217ec208SDavid C Somayajulu 	if (!ecore_iov_vf_has_vport_instance(p_hwfn, vfid)) {
7722217ec208SDavid C Somayajulu 		QL_DPRINT1(((qlnx_host_t *)p_hwfn->p_dev),
7723217ec208SDavid C Somayajulu 			"VF[%d] vport not initialized\n", vfid);
7724217ec208SDavid C Somayajulu 		return ECORE_INVAL;
7725217ec208SDavid C Somayajulu 	}
7726217ec208SDavid C Somayajulu 
7727217ec208SDavid C Somayajulu         vf = ecore_iov_get_public_vf_info(p_hwfn, vfid, true);
7728217ec208SDavid C Somayajulu         if (!vf)
7729217ec208SDavid C Somayajulu                 return -EINVAL;
7730217ec208SDavid C Somayajulu 
7731217ec208SDavid C Somayajulu         /* No real decision to make; Store the configured MAC */
7732217ec208SDavid C Somayajulu         if (params->type == ECORE_FILTER_MAC ||
7733217ec208SDavid C Somayajulu             params->type == ECORE_FILTER_MAC_VLAN)
7734217ec208SDavid C Somayajulu                 memcpy(params->mac, vf->forced_mac, ETH_ALEN);
7735217ec208SDavid C Somayajulu 
7736217ec208SDavid C Somayajulu         return 0;
7737217ec208SDavid C Somayajulu }
7738217ec208SDavid C Somayajulu 
7739217ec208SDavid C Somayajulu int
qlnx_iov_chk_ucast(void * p_hwfn,int vfid,void * params)7740217ec208SDavid C Somayajulu qlnx_iov_chk_ucast(void *p_hwfn, int vfid, void *params)
7741217ec208SDavid C Somayajulu {
7742217ec208SDavid C Somayajulu 	return (__qlnx_iov_chk_ucast(p_hwfn, vfid, params));
7743217ec208SDavid C Somayajulu }
7744217ec208SDavid C Somayajulu 
7745217ec208SDavid C Somayajulu static int
__qlnx_iov_update_vport(struct ecore_hwfn * hwfn,uint8_t vfid,struct ecore_sp_vport_update_params * params,uint16_t * tlvs)7746217ec208SDavid C Somayajulu __qlnx_iov_update_vport(struct ecore_hwfn *hwfn, uint8_t vfid,
7747217ec208SDavid C Somayajulu         struct ecore_sp_vport_update_params *params, uint16_t * tlvs)
7748217ec208SDavid C Somayajulu {
7749217ec208SDavid C Somayajulu 	if (!ecore_iov_vf_has_vport_instance(hwfn, vfid)) {
7750217ec208SDavid C Somayajulu 		QL_DPRINT1(((qlnx_host_t *)hwfn->p_dev),
7751217ec208SDavid C Somayajulu 			"VF[%d] vport not initialized\n", vfid);
7752217ec208SDavid C Somayajulu 		return ECORE_INVAL;
7753217ec208SDavid C Somayajulu 	}
7754217ec208SDavid C Somayajulu 
7755217ec208SDavid C Somayajulu         /* Untrusted VFs can't even be trusted to know that fact.
7756217ec208SDavid C Somayajulu          * Simply indicate everything is configured fine, and trace
7757217ec208SDavid C Somayajulu          * configuration 'behind their back'.
7758217ec208SDavid C Somayajulu          */
7759217ec208SDavid C Somayajulu         if (!(*tlvs & BIT(ECORE_IOV_VP_UPDATE_ACCEPT_PARAM)))
7760217ec208SDavid C Somayajulu                 return 0;
7761217ec208SDavid C Somayajulu 
7762217ec208SDavid C Somayajulu         return 0;
7763217ec208SDavid C Somayajulu 
7764217ec208SDavid C Somayajulu }
7765217ec208SDavid C Somayajulu int
qlnx_iov_update_vport(void * hwfn,uint8_t vfid,void * params,uint16_t * tlvs)7766217ec208SDavid C Somayajulu qlnx_iov_update_vport(void *hwfn, uint8_t vfid, void *params, uint16_t *tlvs)
7767217ec208SDavid C Somayajulu {
7768217ec208SDavid C Somayajulu 	return(__qlnx_iov_update_vport(hwfn, vfid, params, tlvs));
7769217ec208SDavid C Somayajulu }
7770217ec208SDavid C Somayajulu 
7771217ec208SDavid C Somayajulu static int
qlnx_find_hwfn_index(struct ecore_hwfn * p_hwfn)7772217ec208SDavid C Somayajulu qlnx_find_hwfn_index(struct ecore_hwfn *p_hwfn)
7773217ec208SDavid C Somayajulu {
7774217ec208SDavid C Somayajulu 	int			i;
7775217ec208SDavid C Somayajulu 	struct ecore_dev	*cdev;
7776217ec208SDavid C Somayajulu 
7777217ec208SDavid C Somayajulu 	cdev = p_hwfn->p_dev;
7778217ec208SDavid C Somayajulu 
7779217ec208SDavid C Somayajulu 	for (i = 0; i < cdev->num_hwfns; i++) {
7780217ec208SDavid C Somayajulu 		if (&cdev->hwfns[i] == p_hwfn)
7781217ec208SDavid C Somayajulu 			break;
7782217ec208SDavid C Somayajulu 	}
7783217ec208SDavid C Somayajulu 
7784217ec208SDavid C Somayajulu 	if (i >= cdev->num_hwfns)
7785217ec208SDavid C Somayajulu 		return (-1);
7786217ec208SDavid C Somayajulu 
7787217ec208SDavid C Somayajulu 	return (i);
7788217ec208SDavid C Somayajulu }
7789217ec208SDavid C Somayajulu 
7790217ec208SDavid C Somayajulu static int
__qlnx_pf_vf_msg(struct ecore_hwfn * p_hwfn,uint16_t rel_vf_id)7791217ec208SDavid C Somayajulu __qlnx_pf_vf_msg(struct ecore_hwfn *p_hwfn, uint16_t rel_vf_id)
7792217ec208SDavid C Somayajulu {
7793217ec208SDavid C Somayajulu 	qlnx_host_t *ha = (qlnx_host_t *)p_hwfn->p_dev;
7794217ec208SDavid C Somayajulu 	int i;
7795217ec208SDavid C Somayajulu 
7796217ec208SDavid C Somayajulu 	QL_DPRINT2(ha, "ha = %p cdev = %p p_hwfn = %p rel_vf_id = %d\n",
7797217ec208SDavid C Somayajulu 		ha, p_hwfn->p_dev, p_hwfn, rel_vf_id);
7798217ec208SDavid C Somayajulu 
7799217ec208SDavid C Somayajulu 	if ((i = qlnx_find_hwfn_index(p_hwfn)) == -1)
7800217ec208SDavid C Somayajulu 		return (-1);
7801217ec208SDavid C Somayajulu 
7802217ec208SDavid C Somayajulu 	if (ha->sriov_task[i].pf_taskqueue != NULL) {
7803217ec208SDavid C Somayajulu 		atomic_testandset_32(&ha->sriov_task[i].flags,
7804217ec208SDavid C Somayajulu 			QLNX_SRIOV_TASK_FLAGS_VF_PF_MSG);
7805217ec208SDavid C Somayajulu 
7806217ec208SDavid C Somayajulu 		taskqueue_enqueue(ha->sriov_task[i].pf_taskqueue,
7807217ec208SDavid C Somayajulu 			&ha->sriov_task[i].pf_task);
7808217ec208SDavid C Somayajulu 	}
7809217ec208SDavid C Somayajulu 
7810217ec208SDavid C Somayajulu 	return (ECORE_SUCCESS);
7811217ec208SDavid C Somayajulu }
7812217ec208SDavid C Somayajulu 
7813217ec208SDavid C Somayajulu int
qlnx_pf_vf_msg(void * p_hwfn,uint16_t relative_vf_id)7814217ec208SDavid C Somayajulu qlnx_pf_vf_msg(void *p_hwfn, uint16_t relative_vf_id)
7815217ec208SDavid C Somayajulu {
7816217ec208SDavid C Somayajulu 	return (__qlnx_pf_vf_msg(p_hwfn, relative_vf_id));
7817217ec208SDavid C Somayajulu }
7818217ec208SDavid C Somayajulu 
7819217ec208SDavid C Somayajulu static void
__qlnx_vf_flr_update(struct ecore_hwfn * p_hwfn)7820217ec208SDavid C Somayajulu __qlnx_vf_flr_update(struct ecore_hwfn *p_hwfn)
7821217ec208SDavid C Somayajulu {
7822217ec208SDavid C Somayajulu 	qlnx_host_t *ha = (qlnx_host_t *)p_hwfn->p_dev;
7823217ec208SDavid C Somayajulu 	int i;
7824217ec208SDavid C Somayajulu 
7825217ec208SDavid C Somayajulu 	if (!ha->sriov_initialized)
7826217ec208SDavid C Somayajulu 		return;
7827217ec208SDavid C Somayajulu 
7828217ec208SDavid C Somayajulu 	QL_DPRINT2(ha,  "ha = %p cdev = %p p_hwfn = %p \n",
7829217ec208SDavid C Somayajulu 		ha, p_hwfn->p_dev, p_hwfn);
7830217ec208SDavid C Somayajulu 
7831217ec208SDavid C Somayajulu 	if ((i = qlnx_find_hwfn_index(p_hwfn)) == -1)
7832217ec208SDavid C Somayajulu 		return;
7833217ec208SDavid C Somayajulu 
7834217ec208SDavid C Somayajulu 	if (ha->sriov_task[i].pf_taskqueue != NULL) {
7835217ec208SDavid C Somayajulu 		atomic_testandset_32(&ha->sriov_task[i].flags,
7836217ec208SDavid C Somayajulu 			QLNX_SRIOV_TASK_FLAGS_VF_FLR_UPDATE);
7837217ec208SDavid C Somayajulu 
7838217ec208SDavid C Somayajulu 		taskqueue_enqueue(ha->sriov_task[i].pf_taskqueue,
7839217ec208SDavid C Somayajulu 			&ha->sriov_task[i].pf_task);
7840217ec208SDavid C Somayajulu 	}
7841217ec208SDavid C Somayajulu 
7842217ec208SDavid C Somayajulu 	return;
7843217ec208SDavid C Somayajulu }
7844217ec208SDavid C Somayajulu 
7845217ec208SDavid C Somayajulu void
qlnx_vf_flr_update(void * p_hwfn)7846217ec208SDavid C Somayajulu qlnx_vf_flr_update(void *p_hwfn)
7847217ec208SDavid C Somayajulu {
7848217ec208SDavid C Somayajulu 	__qlnx_vf_flr_update(p_hwfn);
7849217ec208SDavid C Somayajulu 
7850217ec208SDavid C Somayajulu 	return;
7851217ec208SDavid C Somayajulu }
7852217ec208SDavid C Somayajulu 
7853217ec208SDavid C Somayajulu #ifndef QLNX_VF
7854217ec208SDavid C Somayajulu 
7855217ec208SDavid C Somayajulu static void
qlnx_vf_bulleting_update(struct ecore_hwfn * p_hwfn)7856217ec208SDavid C Somayajulu qlnx_vf_bulleting_update(struct ecore_hwfn *p_hwfn)
7857217ec208SDavid C Somayajulu {
7858217ec208SDavid C Somayajulu 	qlnx_host_t *ha = (qlnx_host_t *)p_hwfn->p_dev;
7859217ec208SDavid C Somayajulu 	int i;
7860217ec208SDavid C Somayajulu 
7861217ec208SDavid C Somayajulu 	QL_DPRINT2(ha,  "ha = %p cdev = %p p_hwfn = %p \n",
7862217ec208SDavid C Somayajulu 		ha, p_hwfn->p_dev, p_hwfn);
7863217ec208SDavid C Somayajulu 
7864217ec208SDavid C Somayajulu 	if ((i = qlnx_find_hwfn_index(p_hwfn)) == -1)
7865217ec208SDavid C Somayajulu 		return;
7866217ec208SDavid C Somayajulu 
7867217ec208SDavid C Somayajulu 	QL_DPRINT2(ha,  "ha = %p cdev = %p p_hwfn = %p i = %d\n",
7868217ec208SDavid C Somayajulu 		ha, p_hwfn->p_dev, p_hwfn, i);
7869217ec208SDavid C Somayajulu 
7870217ec208SDavid C Somayajulu 	if (ha->sriov_task[i].pf_taskqueue != NULL) {
7871217ec208SDavid C Somayajulu 		atomic_testandset_32(&ha->sriov_task[i].flags,
7872217ec208SDavid C Somayajulu 			QLNX_SRIOV_TASK_FLAGS_BULLETIN_UPDATE);
7873217ec208SDavid C Somayajulu 
7874217ec208SDavid C Somayajulu 		taskqueue_enqueue(ha->sriov_task[i].pf_taskqueue,
7875217ec208SDavid C Somayajulu 			&ha->sriov_task[i].pf_task);
7876217ec208SDavid C Somayajulu 	}
7877217ec208SDavid C Somayajulu }
7878217ec208SDavid C Somayajulu 
7879217ec208SDavid C Somayajulu static void
qlnx_initialize_sriov(qlnx_host_t * ha)7880217ec208SDavid C Somayajulu qlnx_initialize_sriov(qlnx_host_t *ha)
7881217ec208SDavid C Somayajulu {
7882217ec208SDavid C Somayajulu 	device_t	dev;
7883217ec208SDavid C Somayajulu 	nvlist_t	*pf_schema, *vf_schema;
7884217ec208SDavid C Somayajulu 	int		iov_error;
7885217ec208SDavid C Somayajulu 
7886217ec208SDavid C Somayajulu 	dev = ha->pci_dev;
7887217ec208SDavid C Somayajulu 
7888217ec208SDavid C Somayajulu 	pf_schema = pci_iov_schema_alloc_node();
7889217ec208SDavid C Somayajulu 	vf_schema = pci_iov_schema_alloc_node();
7890217ec208SDavid C Somayajulu 
7891217ec208SDavid C Somayajulu 	pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL);
7892217ec208SDavid C Somayajulu 	pci_iov_schema_add_bool(vf_schema, "allow-set-mac",
7893217ec208SDavid C Somayajulu 		IOV_SCHEMA_HASDEFAULT, FALSE);
7894217ec208SDavid C Somayajulu 	pci_iov_schema_add_bool(vf_schema, "allow-promisc",
7895217ec208SDavid C Somayajulu 		IOV_SCHEMA_HASDEFAULT, FALSE);
7896217ec208SDavid C Somayajulu 	pci_iov_schema_add_uint16(vf_schema, "num-queues",
7897217ec208SDavid C Somayajulu 		IOV_SCHEMA_HASDEFAULT, 1);
7898217ec208SDavid C Somayajulu 
7899217ec208SDavid C Somayajulu 	iov_error = pci_iov_attach(dev, pf_schema, vf_schema);
7900217ec208SDavid C Somayajulu 
7901217ec208SDavid C Somayajulu 	if (iov_error != 0) {
7902217ec208SDavid C Somayajulu 		ha->sriov_initialized = 0;
7903217ec208SDavid C Somayajulu 	} else {
7904217ec208SDavid C Somayajulu 		device_printf(dev, "SRIOV initialized\n");
7905217ec208SDavid C Somayajulu 		ha->sriov_initialized = 1;
7906217ec208SDavid C Somayajulu 	}
7907217ec208SDavid C Somayajulu 
7908217ec208SDavid C Somayajulu 	return;
7909217ec208SDavid C Somayajulu }
7910217ec208SDavid C Somayajulu 
7911217ec208SDavid C Somayajulu static void
qlnx_sriov_disable(qlnx_host_t * ha)7912217ec208SDavid C Somayajulu qlnx_sriov_disable(qlnx_host_t *ha)
7913217ec208SDavid C Somayajulu {
7914217ec208SDavid C Somayajulu 	struct ecore_dev *cdev;
7915217ec208SDavid C Somayajulu 	int i, j;
7916217ec208SDavid C Somayajulu 
7917217ec208SDavid C Somayajulu 	cdev = &ha->cdev;
7918217ec208SDavid C Somayajulu 
7919217ec208SDavid C Somayajulu 	ecore_iov_set_vfs_to_disable(cdev, true);
7920217ec208SDavid C Somayajulu 
7921217ec208SDavid C Somayajulu 	for_each_hwfn(cdev, i) {
7922217ec208SDavid C Somayajulu 		struct ecore_hwfn *hwfn = &cdev->hwfns[i];
7923217ec208SDavid C Somayajulu 		struct ecore_ptt *ptt = ecore_ptt_acquire(hwfn);
7924217ec208SDavid C Somayajulu 
7925217ec208SDavid C Somayajulu 		if (!ptt) {
7926217ec208SDavid C Somayajulu 			QL_DPRINT1(ha, "Failed to acquire ptt\n");
7927217ec208SDavid C Somayajulu 			return;
7928217ec208SDavid C Somayajulu 		}
7929217ec208SDavid C Somayajulu 		/* Clean WFQ db and configure equal weight for all vports */
7930217ec208SDavid C Somayajulu 		ecore_clean_wfq_db(hwfn, ptt);
7931217ec208SDavid C Somayajulu 
7932217ec208SDavid C Somayajulu 		ecore_for_each_vf(hwfn, j) {
7933217ec208SDavid C Somayajulu 			int k = 0;
7934217ec208SDavid C Somayajulu 
7935217ec208SDavid C Somayajulu 			if (!ecore_iov_is_valid_vfid(hwfn, j, true, false))
7936217ec208SDavid C Somayajulu 				continue;
7937217ec208SDavid C Somayajulu 
7938217ec208SDavid C Somayajulu 			if (ecore_iov_is_vf_started(hwfn, j)) {
7939217ec208SDavid C Somayajulu 				/* Wait until VF is disabled before releasing */
7940217ec208SDavid C Somayajulu 
7941217ec208SDavid C Somayajulu 				for (k = 0; k < 100; k++) {
7942217ec208SDavid C Somayajulu 					if (!ecore_iov_is_vf_stopped(hwfn, j)) {
7943217ec208SDavid C Somayajulu 						qlnx_mdelay(__func__, 10);
7944217ec208SDavid C Somayajulu 					} else
7945217ec208SDavid C Somayajulu 						break;
7946217ec208SDavid C Somayajulu 				}
7947217ec208SDavid C Somayajulu 			}
7948217ec208SDavid C Somayajulu 
7949217ec208SDavid C Somayajulu 			if (k < 100)
7950217ec208SDavid C Somayajulu 				ecore_iov_release_hw_for_vf(&cdev->hwfns[i],
7951217ec208SDavid C Somayajulu                                                           ptt, j);
7952217ec208SDavid C Somayajulu 			else {
7953217ec208SDavid C Somayajulu 				QL_DPRINT1(ha,
7954217ec208SDavid C Somayajulu 					"Timeout waiting for VF's FLR to end\n");
7955217ec208SDavid C Somayajulu 			}
7956217ec208SDavid C Somayajulu 		}
7957217ec208SDavid C Somayajulu 		ecore_ptt_release(hwfn, ptt);
7958217ec208SDavid C Somayajulu 	}
7959217ec208SDavid C Somayajulu 
7960217ec208SDavid C Somayajulu 	ecore_iov_set_vfs_to_disable(cdev, false);
7961217ec208SDavid C Somayajulu 
7962217ec208SDavid C Somayajulu 	return;
7963217ec208SDavid C Somayajulu }
7964217ec208SDavid C Somayajulu 
7965217ec208SDavid C Somayajulu static void
qlnx_sriov_enable_qid_config(struct ecore_hwfn * hwfn,u16 vfid,struct ecore_iov_vf_init_params * params)7966217ec208SDavid C Somayajulu qlnx_sriov_enable_qid_config(struct ecore_hwfn *hwfn, u16 vfid,
7967217ec208SDavid C Somayajulu 	struct ecore_iov_vf_init_params *params)
7968217ec208SDavid C Somayajulu {
7969217ec208SDavid C Somayajulu         u16 base, i;
7970217ec208SDavid C Somayajulu 
7971217ec208SDavid C Somayajulu         /* Since we have an equal resource distribution per-VF, and we assume
7972217ec208SDavid C Somayajulu          * PF has acquired the ECORE_PF_L2_QUE first queues, we start setting
7973217ec208SDavid C Somayajulu          * sequentially from there.
7974217ec208SDavid C Somayajulu          */
7975217ec208SDavid C Somayajulu         base = FEAT_NUM(hwfn, ECORE_PF_L2_QUE) + vfid * params->num_queues;
7976217ec208SDavid C Somayajulu 
7977217ec208SDavid C Somayajulu         params->rel_vf_id = vfid;
7978217ec208SDavid C Somayajulu 
7979217ec208SDavid C Somayajulu         for (i = 0; i < params->num_queues; i++) {
7980217ec208SDavid C Somayajulu                 params->req_rx_queue[i] = base + i;
7981217ec208SDavid C Somayajulu                 params->req_tx_queue[i] = base + i;
7982217ec208SDavid C Somayajulu         }
7983217ec208SDavid C Somayajulu 
7984217ec208SDavid C Somayajulu         /* PF uses indices 0 for itself; Set vport/RSS afterwards */
7985217ec208SDavid C Somayajulu         params->vport_id = vfid + 1;
7986217ec208SDavid C Somayajulu         params->rss_eng_id = vfid + 1;
7987217ec208SDavid C Somayajulu 
7988217ec208SDavid C Somayajulu 	return;
7989217ec208SDavid C Somayajulu }
7990217ec208SDavid C Somayajulu 
7991217ec208SDavid C Somayajulu static int
qlnx_iov_init(device_t dev,uint16_t num_vfs,const nvlist_t * nvlist_params)7992217ec208SDavid C Somayajulu qlnx_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *nvlist_params)
7993217ec208SDavid C Somayajulu {
7994217ec208SDavid C Somayajulu 	qlnx_host_t		*ha;
7995217ec208SDavid C Somayajulu 	struct ecore_dev	*cdev;
7996217ec208SDavid C Somayajulu 	struct ecore_iov_vf_init_params params;
7997217ec208SDavid C Somayajulu 	int ret, j, i;
7998217ec208SDavid C Somayajulu 	uint32_t max_vfs;
7999217ec208SDavid C Somayajulu 
8000217ec208SDavid C Somayajulu 	if ((ha = device_get_softc(dev)) == NULL) {
8001217ec208SDavid C Somayajulu 		device_printf(dev, "%s: cannot get softc\n", __func__);
8002217ec208SDavid C Somayajulu 		return (-1);
8003217ec208SDavid C Somayajulu 	}
8004217ec208SDavid C Somayajulu 
8005217ec208SDavid C Somayajulu 	if (qlnx_create_pf_taskqueues(ha) != 0)
8006217ec208SDavid C Somayajulu 		goto qlnx_iov_init_err0;
8007217ec208SDavid C Somayajulu 
8008217ec208SDavid C Somayajulu 	cdev = &ha->cdev;
8009217ec208SDavid C Somayajulu 
8010217ec208SDavid C Somayajulu 	max_vfs = RESC_NUM(&cdev->hwfns[0], ECORE_VPORT);
8011217ec208SDavid C Somayajulu 
8012217ec208SDavid C Somayajulu 	QL_DPRINT2(ha," dev = %p enter num_vfs = %d max_vfs = %d\n",
8013217ec208SDavid C Somayajulu 		dev, num_vfs, max_vfs);
8014217ec208SDavid C Somayajulu 
8015217ec208SDavid C Somayajulu         if (num_vfs >= max_vfs) {
8016217ec208SDavid C Somayajulu                 QL_DPRINT1(ha, "Can start at most %d VFs\n",
8017217ec208SDavid C Somayajulu                           (RESC_NUM(&cdev->hwfns[0], ECORE_VPORT) - 1));
8018217ec208SDavid C Somayajulu 		goto qlnx_iov_init_err0;
8019217ec208SDavid C Somayajulu         }
8020217ec208SDavid C Somayajulu 
8021217ec208SDavid C Somayajulu 	ha->vf_attr =  malloc(((sizeof (qlnx_vf_attr_t) * num_vfs)), M_QLNXBUF,
8022217ec208SDavid C Somayajulu 				M_NOWAIT);
8023217ec208SDavid C Somayajulu 
8024217ec208SDavid C Somayajulu 	if (ha->vf_attr == NULL)
8025217ec208SDavid C Somayajulu 		goto qlnx_iov_init_err0;
8026217ec208SDavid C Somayajulu 
8027217ec208SDavid C Somayajulu         memset(&params, 0, sizeof(params));
8028217ec208SDavid C Somayajulu 
8029217ec208SDavid C Somayajulu         /* Initialize HW for VF access */
8030217ec208SDavid C Somayajulu         for_each_hwfn(cdev, j) {
8031217ec208SDavid C Somayajulu                 struct ecore_hwfn *hwfn = &cdev->hwfns[j];
8032217ec208SDavid C Somayajulu                 struct ecore_ptt *ptt = ecore_ptt_acquire(hwfn);
8033217ec208SDavid C Somayajulu 
8034217ec208SDavid C Somayajulu                 /* Make sure not to use more than 16 queues per VF */
8035217ec208SDavid C Somayajulu                 params.num_queues = min_t(int,
8036217ec208SDavid C Somayajulu                                           (FEAT_NUM(hwfn, ECORE_VF_L2_QUE) / num_vfs),
8037217ec208SDavid C Somayajulu                                           16);
8038217ec208SDavid C Somayajulu 
8039217ec208SDavid C Somayajulu                 if (!ptt) {
8040217ec208SDavid C Somayajulu                         QL_DPRINT1(ha, "Failed to acquire ptt\n");
8041217ec208SDavid C Somayajulu                         goto qlnx_iov_init_err1;
8042217ec208SDavid C Somayajulu                 }
8043217ec208SDavid C Somayajulu 
8044217ec208SDavid C Somayajulu                 for (i = 0; i < num_vfs; i++) {
8045217ec208SDavid C Somayajulu                         if (!ecore_iov_is_valid_vfid(hwfn, i, false, true))
8046217ec208SDavid C Somayajulu                                 continue;
8047217ec208SDavid C Somayajulu 
8048217ec208SDavid C Somayajulu                         qlnx_sriov_enable_qid_config(hwfn, i, &params);
8049217ec208SDavid C Somayajulu 
8050217ec208SDavid C Somayajulu                         ret = ecore_iov_init_hw_for_vf(hwfn, ptt, &params);
8051217ec208SDavid C Somayajulu 
8052217ec208SDavid C Somayajulu                         if (ret) {
8053217ec208SDavid C Somayajulu                                 QL_DPRINT1(ha, "Failed to enable VF[%d]\n", i);
8054217ec208SDavid C Somayajulu                                 ecore_ptt_release(hwfn, ptt);
8055217ec208SDavid C Somayajulu                                 goto qlnx_iov_init_err1;
8056217ec208SDavid C Somayajulu                         }
8057217ec208SDavid C Somayajulu                 }
8058217ec208SDavid C Somayajulu 
8059217ec208SDavid C Somayajulu                 ecore_ptt_release(hwfn, ptt);
8060217ec208SDavid C Somayajulu         }
8061217ec208SDavid C Somayajulu 
8062217ec208SDavid C Somayajulu 	ha->num_vfs = num_vfs;
8063217ec208SDavid C Somayajulu 	qlnx_inform_vf_link_state(&cdev->hwfns[0], ha);
8064217ec208SDavid C Somayajulu 
8065217ec208SDavid C Somayajulu 	QL_DPRINT2(ha," dev = %p exit num_vfs = %d\n", dev, num_vfs);
8066217ec208SDavid C Somayajulu 
8067217ec208SDavid C Somayajulu 	return (0);
8068217ec208SDavid C Somayajulu 
8069217ec208SDavid C Somayajulu qlnx_iov_init_err1:
8070217ec208SDavid C Somayajulu 	qlnx_sriov_disable(ha);
8071217ec208SDavid C Somayajulu 
8072217ec208SDavid C Somayajulu qlnx_iov_init_err0:
8073217ec208SDavid C Somayajulu 	qlnx_destroy_pf_taskqueues(ha);
8074217ec208SDavid C Somayajulu 	ha->num_vfs = 0;
8075217ec208SDavid C Somayajulu 
8076217ec208SDavid C Somayajulu 	return (-1);
8077217ec208SDavid C Somayajulu }
8078217ec208SDavid C Somayajulu 
8079217ec208SDavid C Somayajulu static void
qlnx_iov_uninit(device_t dev)8080217ec208SDavid C Somayajulu qlnx_iov_uninit(device_t dev)
8081217ec208SDavid C Somayajulu {
8082217ec208SDavid C Somayajulu 	qlnx_host_t	*ha;
8083217ec208SDavid C Somayajulu 
8084217ec208SDavid C Somayajulu 	if ((ha = device_get_softc(dev)) == NULL) {
8085217ec208SDavid C Somayajulu 		device_printf(dev, "%s: cannot get softc\n", __func__);
8086217ec208SDavid C Somayajulu 		return;
8087217ec208SDavid C Somayajulu 	}
8088217ec208SDavid C Somayajulu 
8089217ec208SDavid C Somayajulu 	QL_DPRINT2(ha," dev = %p enter\n", dev);
8090217ec208SDavid C Somayajulu 
8091217ec208SDavid C Somayajulu 	qlnx_sriov_disable(ha);
8092217ec208SDavid C Somayajulu 	qlnx_destroy_pf_taskqueues(ha);
8093217ec208SDavid C Somayajulu 
8094217ec208SDavid C Somayajulu 	free(ha->vf_attr, M_QLNXBUF);
8095217ec208SDavid C Somayajulu 	ha->vf_attr = NULL;
8096217ec208SDavid C Somayajulu 
8097217ec208SDavid C Somayajulu 	ha->num_vfs = 0;
8098217ec208SDavid C Somayajulu 
8099217ec208SDavid C Somayajulu 	QL_DPRINT2(ha," dev = %p exit\n", dev);
8100217ec208SDavid C Somayajulu 	return;
8101217ec208SDavid C Somayajulu }
8102217ec208SDavid C Somayajulu 
8103217ec208SDavid C Somayajulu static int
qlnx_iov_add_vf(device_t dev,uint16_t vfnum,const nvlist_t * params)8104217ec208SDavid C Somayajulu qlnx_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params)
8105217ec208SDavid C Somayajulu {
8106217ec208SDavid C Somayajulu 	qlnx_host_t	*ha;
8107217ec208SDavid C Somayajulu 	qlnx_vf_attr_t	*vf_attr;
8108217ec208SDavid C Somayajulu 	unsigned const char *mac;
8109217ec208SDavid C Somayajulu 	size_t size;
8110217ec208SDavid C Somayajulu 	struct ecore_hwfn *p_hwfn;
8111217ec208SDavid C Somayajulu 
8112217ec208SDavid C Somayajulu 	if ((ha = device_get_softc(dev)) == NULL) {
8113217ec208SDavid C Somayajulu 		device_printf(dev, "%s: cannot get softc\n", __func__);
8114217ec208SDavid C Somayajulu 		return (-1);
8115217ec208SDavid C Somayajulu 	}
8116217ec208SDavid C Somayajulu 
8117217ec208SDavid C Somayajulu 	QL_DPRINT2(ha," dev = %p enter vfnum = %d\n", dev, vfnum);
8118217ec208SDavid C Somayajulu 
8119217ec208SDavid C Somayajulu 	if (vfnum > (ha->num_vfs - 1)) {
8120217ec208SDavid C Somayajulu 		QL_DPRINT1(ha, " VF[%d] is greater than max allowed [%d]\n",
8121217ec208SDavid C Somayajulu 			vfnum, (ha->num_vfs - 1));
8122217ec208SDavid C Somayajulu 	}
8123217ec208SDavid C Somayajulu 
8124217ec208SDavid C Somayajulu 	vf_attr = &ha->vf_attr[vfnum];
8125217ec208SDavid C Somayajulu 
8126217ec208SDavid C Somayajulu         if (nvlist_exists_binary(params, "mac-addr")) {
8127217ec208SDavid C Somayajulu                 mac = nvlist_get_binary(params, "mac-addr", &size);
8128217ec208SDavid C Somayajulu                 bcopy(mac, vf_attr->mac_addr, ETHER_ADDR_LEN);
8129217ec208SDavid C Somayajulu 		device_printf(dev,
8130217ec208SDavid C Somayajulu 			"%s: mac_addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
8131217ec208SDavid C Somayajulu 			__func__, vf_attr->mac_addr[0],
8132217ec208SDavid C Somayajulu 			vf_attr->mac_addr[1], vf_attr->mac_addr[2],
8133217ec208SDavid C Somayajulu 			vf_attr->mac_addr[3], vf_attr->mac_addr[4],
8134217ec208SDavid C Somayajulu 			vf_attr->mac_addr[5]);
8135217ec208SDavid C Somayajulu 		p_hwfn = &ha->cdev.hwfns[0];
8136217ec208SDavid C Somayajulu 		ecore_iov_bulletin_set_mac(p_hwfn, vf_attr->mac_addr,
8137217ec208SDavid C Somayajulu 			vfnum);
8138217ec208SDavid C Somayajulu 	}
8139217ec208SDavid C Somayajulu 
8140217ec208SDavid C Somayajulu 	QL_DPRINT2(ha," dev = %p exit vfnum = %d\n", dev, vfnum);
8141217ec208SDavid C Somayajulu 	return (0);
8142217ec208SDavid C Somayajulu }
8143217ec208SDavid C Somayajulu 
8144217ec208SDavid C Somayajulu static void
qlnx_handle_vf_msg(qlnx_host_t * ha,struct ecore_hwfn * p_hwfn)8145217ec208SDavid C Somayajulu qlnx_handle_vf_msg(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn)
8146217ec208SDavid C Somayajulu {
8147217ec208SDavid C Somayajulu         uint64_t events[ECORE_VF_ARRAY_LENGTH];
8148217ec208SDavid C Somayajulu         struct ecore_ptt *ptt;
8149217ec208SDavid C Somayajulu         int i;
8150217ec208SDavid C Somayajulu 
8151217ec208SDavid C Somayajulu         ptt = ecore_ptt_acquire(p_hwfn);
8152217ec208SDavid C Somayajulu         if (!ptt) {
8153217ec208SDavid C Somayajulu                 QL_DPRINT1(ha, "Can't acquire PTT; re-scheduling\n");
8154217ec208SDavid C Somayajulu 		__qlnx_pf_vf_msg(p_hwfn, 0);
8155217ec208SDavid C Somayajulu                 return;
8156217ec208SDavid C Somayajulu         }
8157217ec208SDavid C Somayajulu 
8158217ec208SDavid C Somayajulu         ecore_iov_pf_get_pending_events(p_hwfn, events);
8159217ec208SDavid C Somayajulu 
8160217ec208SDavid C Somayajulu         QL_DPRINT2(ha, "Event mask of VF events:"
8161217ec208SDavid C Somayajulu 		"0x%" PRIu64 "0x%" PRIu64 " 0x%" PRIu64 "\n",
8162217ec208SDavid C Somayajulu                    events[0], events[1], events[2]);
8163217ec208SDavid C Somayajulu 
8164217ec208SDavid C Somayajulu         ecore_for_each_vf(p_hwfn, i) {
8165217ec208SDavid C Somayajulu                 /* Skip VFs with no pending messages */
8166217ec208SDavid C Somayajulu                 if (!(events[i / 64] & (1ULL << (i % 64))))
8167217ec208SDavid C Somayajulu                         continue;
8168217ec208SDavid C Somayajulu 
8169217ec208SDavid C Somayajulu 		QL_DPRINT2(ha,
8170217ec208SDavid C Somayajulu                            "Handling VF message from VF 0x%02x [Abs 0x%02x]\n",
8171217ec208SDavid C Somayajulu                            i, p_hwfn->p_dev->p_iov_info->first_vf_in_pf + i);
8172217ec208SDavid C Somayajulu 
8173217ec208SDavid C Somayajulu                 /* Copy VF's message to PF's request buffer for that VF */
8174217ec208SDavid C Somayajulu                 if (ecore_iov_copy_vf_msg(p_hwfn, ptt, i))
8175217ec208SDavid C Somayajulu                         continue;
8176217ec208SDavid C Somayajulu 
8177217ec208SDavid C Somayajulu                 ecore_iov_process_mbx_req(p_hwfn, ptt, i);
8178217ec208SDavid C Somayajulu         }
8179217ec208SDavid C Somayajulu 
8180217ec208SDavid C Somayajulu         ecore_ptt_release(p_hwfn, ptt);
8181217ec208SDavid C Somayajulu 
8182217ec208SDavid C Somayajulu 	return;
8183217ec208SDavid C Somayajulu }
8184217ec208SDavid C Somayajulu 
8185217ec208SDavid C Somayajulu static void
qlnx_handle_vf_flr_update(qlnx_host_t * ha,struct ecore_hwfn * p_hwfn)8186217ec208SDavid C Somayajulu qlnx_handle_vf_flr_update(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn)
8187217ec208SDavid C Somayajulu {
8188217ec208SDavid C Somayajulu         struct ecore_ptt *ptt;
8189217ec208SDavid C Somayajulu 	int ret;
8190217ec208SDavid C Somayajulu 
8191217ec208SDavid C Somayajulu 	ptt = ecore_ptt_acquire(p_hwfn);
8192217ec208SDavid C Somayajulu 
8193217ec208SDavid C Somayajulu 	if (!ptt) {
8194217ec208SDavid C Somayajulu                 QL_DPRINT1(ha, "Can't acquire PTT; re-scheduling\n");
8195217ec208SDavid C Somayajulu 		__qlnx_vf_flr_update(p_hwfn);
8196217ec208SDavid C Somayajulu                 return;
8197217ec208SDavid C Somayajulu 	}
8198217ec208SDavid C Somayajulu 
8199217ec208SDavid C Somayajulu 	ret = ecore_iov_vf_flr_cleanup(p_hwfn, ptt);
8200217ec208SDavid C Somayajulu 
8201217ec208SDavid C Somayajulu 	if (ret) {
8202217ec208SDavid C Somayajulu                 QL_DPRINT1(ha, "ecore_iov_vf_flr_cleanup failed; re-scheduling\n");
8203217ec208SDavid C Somayajulu 	}
8204217ec208SDavid C Somayajulu 
8205217ec208SDavid C Somayajulu 	ecore_ptt_release(p_hwfn, ptt);
8206217ec208SDavid C Somayajulu 
8207217ec208SDavid C Somayajulu 	return;
8208217ec208SDavid C Somayajulu }
8209217ec208SDavid C Somayajulu 
8210217ec208SDavid C Somayajulu static void
qlnx_handle_bulletin_update(qlnx_host_t * ha,struct ecore_hwfn * p_hwfn)8211217ec208SDavid C Somayajulu qlnx_handle_bulletin_update(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn)
8212217ec208SDavid C Somayajulu {
8213217ec208SDavid C Somayajulu         struct ecore_ptt *ptt;
8214217ec208SDavid C Somayajulu 	int i;
8215217ec208SDavid C Somayajulu 
8216217ec208SDavid C Somayajulu 	ptt = ecore_ptt_acquire(p_hwfn);
8217217ec208SDavid C Somayajulu 
8218217ec208SDavid C Somayajulu 	if (!ptt) {
8219217ec208SDavid C Somayajulu                 QL_DPRINT1(ha, "Can't acquire PTT; re-scheduling\n");
8220217ec208SDavid C Somayajulu 		qlnx_vf_bulleting_update(p_hwfn);
8221217ec208SDavid C Somayajulu                 return;
8222217ec208SDavid C Somayajulu 	}
8223217ec208SDavid C Somayajulu 
8224217ec208SDavid C Somayajulu 	ecore_for_each_vf(p_hwfn, i) {
8225217ec208SDavid C Somayajulu 		QL_DPRINT1(ha, "ecore_iov_post_vf_bulletin[%p, %d]\n",
8226217ec208SDavid C Somayajulu 			p_hwfn, i);
8227217ec208SDavid C Somayajulu 		ecore_iov_post_vf_bulletin(p_hwfn, i, ptt);
8228217ec208SDavid C Somayajulu 	}
8229217ec208SDavid C Somayajulu 
8230217ec208SDavid C Somayajulu 	ecore_ptt_release(p_hwfn, ptt);
8231217ec208SDavid C Somayajulu 
8232217ec208SDavid C Somayajulu 	return;
8233217ec208SDavid C Somayajulu }
8234217ec208SDavid C Somayajulu 
8235217ec208SDavid C Somayajulu static void
qlnx_pf_taskqueue(void * context,int pending)8236217ec208SDavid C Somayajulu qlnx_pf_taskqueue(void *context, int pending)
8237217ec208SDavid C Somayajulu {
8238217ec208SDavid C Somayajulu 	struct ecore_hwfn	*p_hwfn;
8239217ec208SDavid C Somayajulu 	qlnx_host_t		*ha;
8240217ec208SDavid C Somayajulu 	int			i;
8241217ec208SDavid C Somayajulu 
8242217ec208SDavid C Somayajulu 	p_hwfn = context;
8243217ec208SDavid C Somayajulu 
8244217ec208SDavid C Somayajulu 	if (p_hwfn == NULL)
8245217ec208SDavid C Somayajulu 		return;
8246217ec208SDavid C Somayajulu 
8247217ec208SDavid C Somayajulu 	ha = (qlnx_host_t *)(p_hwfn->p_dev);
8248217ec208SDavid C Somayajulu 
8249217ec208SDavid C Somayajulu 	if ((i = qlnx_find_hwfn_index(p_hwfn)) == -1)
8250217ec208SDavid C Somayajulu 		return;
8251217ec208SDavid C Somayajulu 
8252217ec208SDavid C Somayajulu 	if (atomic_testandclear_32(&ha->sriov_task[i].flags,
8253217ec208SDavid C Somayajulu 		QLNX_SRIOV_TASK_FLAGS_VF_PF_MSG))
8254217ec208SDavid C Somayajulu 		qlnx_handle_vf_msg(ha, p_hwfn);
8255217ec208SDavid C Somayajulu 
8256217ec208SDavid C Somayajulu 	if (atomic_testandclear_32(&ha->sriov_task[i].flags,
8257217ec208SDavid C Somayajulu 		QLNX_SRIOV_TASK_FLAGS_VF_FLR_UPDATE))
8258217ec208SDavid C Somayajulu 		qlnx_handle_vf_flr_update(ha, p_hwfn);
8259217ec208SDavid C Somayajulu 
8260217ec208SDavid C Somayajulu 	if (atomic_testandclear_32(&ha->sriov_task[i].flags,
8261217ec208SDavid C Somayajulu 		QLNX_SRIOV_TASK_FLAGS_BULLETIN_UPDATE))
8262217ec208SDavid C Somayajulu 		qlnx_handle_bulletin_update(ha, p_hwfn);
8263217ec208SDavid C Somayajulu 
8264217ec208SDavid C Somayajulu 	return;
8265217ec208SDavid C Somayajulu }
8266217ec208SDavid C Somayajulu 
8267217ec208SDavid C Somayajulu static int
qlnx_create_pf_taskqueues(qlnx_host_t * ha)8268217ec208SDavid C Somayajulu qlnx_create_pf_taskqueues(qlnx_host_t *ha)
8269217ec208SDavid C Somayajulu {
8270217ec208SDavid C Somayajulu 	int	i;
8271217ec208SDavid C Somayajulu 	uint8_t	tq_name[32];
8272217ec208SDavid C Somayajulu 
8273217ec208SDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
8274217ec208SDavid C Somayajulu                 struct ecore_hwfn *p_hwfn = &ha->cdev.hwfns[i];
8275217ec208SDavid C Somayajulu 
8276217ec208SDavid C Somayajulu 		bzero(tq_name, sizeof (tq_name));
8277217ec208SDavid C Somayajulu 		snprintf(tq_name, sizeof (tq_name), "ql_pf_tq_%d", i);
8278217ec208SDavid C Somayajulu 
8279217ec208SDavid C Somayajulu 		TASK_INIT(&ha->sriov_task[i].pf_task, 0, qlnx_pf_taskqueue, p_hwfn);
8280217ec208SDavid C Somayajulu 
8281217ec208SDavid C Somayajulu 		ha->sriov_task[i].pf_taskqueue = taskqueue_create(tq_name, M_NOWAIT,
8282217ec208SDavid C Somayajulu 			 taskqueue_thread_enqueue,
8283217ec208SDavid C Somayajulu 			&ha->sriov_task[i].pf_taskqueue);
8284217ec208SDavid C Somayajulu 
8285217ec208SDavid C Somayajulu 		if (ha->sriov_task[i].pf_taskqueue == NULL)
8286217ec208SDavid C Somayajulu 			return (-1);
8287217ec208SDavid C Somayajulu 
8288217ec208SDavid C Somayajulu 		taskqueue_start_threads(&ha->sriov_task[i].pf_taskqueue, 1,
8289217ec208SDavid C Somayajulu 			PI_NET, "%s", tq_name);
8290217ec208SDavid C Somayajulu 
8291217ec208SDavid C Somayajulu 		QL_DPRINT1(ha, "%p\n", ha->sriov_task[i].pf_taskqueue);
8292217ec208SDavid C Somayajulu 	}
8293217ec208SDavid C Somayajulu 
8294217ec208SDavid C Somayajulu 	return (0);
8295217ec208SDavid C Somayajulu }
8296217ec208SDavid C Somayajulu 
8297217ec208SDavid C Somayajulu static void
qlnx_destroy_pf_taskqueues(qlnx_host_t * ha)8298217ec208SDavid C Somayajulu qlnx_destroy_pf_taskqueues(qlnx_host_t *ha)
8299217ec208SDavid C Somayajulu {
8300217ec208SDavid C Somayajulu 	int	i;
8301217ec208SDavid C Somayajulu 
8302217ec208SDavid C Somayajulu 	for (i = 0; i < ha->cdev.num_hwfns; i++) {
8303217ec208SDavid C Somayajulu 		if (ha->sriov_task[i].pf_taskqueue != NULL) {
8304217ec208SDavid C Somayajulu 			taskqueue_drain(ha->sriov_task[i].pf_taskqueue,
8305217ec208SDavid C Somayajulu 				&ha->sriov_task[i].pf_task);
8306217ec208SDavid C Somayajulu 			taskqueue_free(ha->sriov_task[i].pf_taskqueue);
8307217ec208SDavid C Somayajulu 			ha->sriov_task[i].pf_taskqueue = NULL;
8308217ec208SDavid C Somayajulu 		}
8309217ec208SDavid C Somayajulu 	}
8310217ec208SDavid C Somayajulu 	return;
8311217ec208SDavid C Somayajulu }
8312217ec208SDavid C Somayajulu 
8313217ec208SDavid C Somayajulu static void
qlnx_inform_vf_link_state(struct ecore_hwfn * p_hwfn,qlnx_host_t * ha)8314217ec208SDavid C Somayajulu qlnx_inform_vf_link_state(struct ecore_hwfn *p_hwfn, qlnx_host_t *ha)
8315217ec208SDavid C Somayajulu {
8316217ec208SDavid C Somayajulu 	struct ecore_mcp_link_capabilities caps;
8317217ec208SDavid C Somayajulu 	struct ecore_mcp_link_params params;
8318217ec208SDavid C Somayajulu 	struct ecore_mcp_link_state link;
8319217ec208SDavid C Somayajulu 	int i;
8320217ec208SDavid C Somayajulu 
8321217ec208SDavid C Somayajulu 	if (!p_hwfn->pf_iov_info)
8322217ec208SDavid C Somayajulu 		return;
8323217ec208SDavid C Somayajulu 
8324217ec208SDavid C Somayajulu 	memset(&params, 0, sizeof(struct ecore_mcp_link_params));
8325217ec208SDavid C Somayajulu 	memset(&link, 0, sizeof(struct ecore_mcp_link_state));
8326217ec208SDavid C Somayajulu 	memset(&caps, 0, sizeof(struct ecore_mcp_link_capabilities));
8327217ec208SDavid C Somayajulu 
8328217ec208SDavid C Somayajulu 	memcpy(&caps, ecore_mcp_get_link_capabilities(p_hwfn), sizeof(caps));
8329217ec208SDavid C Somayajulu         memcpy(&link, ecore_mcp_get_link_state(p_hwfn), sizeof(link));
8330217ec208SDavid C Somayajulu         memcpy(&params, ecore_mcp_get_link_params(p_hwfn), sizeof(params));
8331217ec208SDavid C Somayajulu 
8332217ec208SDavid C Somayajulu 	QL_DPRINT2(ha, "called\n");
8333217ec208SDavid C Somayajulu 
8334217ec208SDavid C Somayajulu         /* Update bulletin of all future possible VFs with link configuration */
8335217ec208SDavid C Somayajulu         for (i = 0; i < p_hwfn->p_dev->p_iov_info->total_vfs; i++) {
8336217ec208SDavid C Somayajulu                 /* Modify link according to the VF's configured link state */
8337217ec208SDavid C Somayajulu 
8338217ec208SDavid C Somayajulu                 link.link_up = false;
8339217ec208SDavid C Somayajulu 
8340217ec208SDavid C Somayajulu                 if (ha->link_up) {
8341217ec208SDavid C Somayajulu                         link.link_up = true;
8342217ec208SDavid C Somayajulu                         /* Set speed according to maximum supported by HW.
8343217ec208SDavid C Somayajulu                          * that is 40G for regular devices and 100G for CMT
8344217ec208SDavid C Somayajulu                          * mode devices.
8345217ec208SDavid C Somayajulu                          */
8346217ec208SDavid C Somayajulu                         link.speed = (p_hwfn->p_dev->num_hwfns > 1) ?
8347217ec208SDavid C Somayajulu 						100000 : link.speed;
8348217ec208SDavid C Somayajulu 		}
8349217ec208SDavid C Somayajulu 		QL_DPRINT2(ha, "link [%d] = %d\n", i, link.link_up);
8350217ec208SDavid C Somayajulu                 ecore_iov_set_link(p_hwfn, i, &params, &link, &caps);
8351217ec208SDavid C Somayajulu         }
8352217ec208SDavid C Somayajulu 
8353217ec208SDavid C Somayajulu 	qlnx_vf_bulleting_update(p_hwfn);
8354217ec208SDavid C Somayajulu 
8355217ec208SDavid C Somayajulu 	return;
8356217ec208SDavid C Somayajulu }
8357217ec208SDavid C Somayajulu #endif /* #ifndef QLNX_VF */
8358217ec208SDavid C Somayajulu #endif /* #ifdef CONFIG_ECORE_SRIOV */
8359