xref: /openbmc/linux/drivers/net/ethernet/cavium/liquidio/lio_main.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1f21fb3edSRaghu Vatsavayi /**********************************************************************
2f21fb3edSRaghu Vatsavayi  * Author: Cavium, Inc.
3f21fb3edSRaghu Vatsavayi  *
4f21fb3edSRaghu Vatsavayi  * Contact: support@cavium.com
5f21fb3edSRaghu Vatsavayi  *          Please include "LiquidIO" in the subject.
6f21fb3edSRaghu Vatsavayi  *
750579d3dSRaghu Vatsavayi  * Copyright (c) 2003-2016 Cavium, Inc.
8f21fb3edSRaghu Vatsavayi  *
9f21fb3edSRaghu Vatsavayi  * This file is free software; you can redistribute it and/or modify
10f21fb3edSRaghu Vatsavayi  * it under the terms of the GNU General Public License, Version 2, as
11f21fb3edSRaghu Vatsavayi  * published by the Free Software Foundation.
12f21fb3edSRaghu Vatsavayi  *
13f21fb3edSRaghu Vatsavayi  * This file is distributed in the hope that it will be useful, but
14f21fb3edSRaghu Vatsavayi  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15f21fb3edSRaghu Vatsavayi  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1650579d3dSRaghu Vatsavayi  * NONINFRINGEMENT.  See the GNU General Public License for more details.
1750579d3dSRaghu Vatsavayi  ***********************************************************************/
18e3bfc6e7SRussell King #include <linux/module.h>
19282ccf6eSFlorian Westphal #include <linux/interrupt.h>
20f21fb3edSRaghu Vatsavayi #include <linux/pci.h>
21f21fb3edSRaghu Vatsavayi #include <linux/firmware.h>
2201fb237aSRaghu Vatsavayi #include <net/vxlan.h>
239ff1a9baSRaghu Vatsavayi #include <linux/kthread.h>
24f21fb3edSRaghu Vatsavayi #include "liquidio_common.h"
25f21fb3edSRaghu Vatsavayi #include "octeon_droq.h"
26f21fb3edSRaghu Vatsavayi #include "octeon_iq.h"
27f21fb3edSRaghu Vatsavayi #include "response_manager.h"
28f21fb3edSRaghu Vatsavayi #include "octeon_device.h"
29f21fb3edSRaghu Vatsavayi #include "octeon_nic.h"
30f21fb3edSRaghu Vatsavayi #include "octeon_main.h"
31f21fb3edSRaghu Vatsavayi #include "octeon_network.h"
32f21fb3edSRaghu Vatsavayi #include "cn66xx_regs.h"
33f21fb3edSRaghu Vatsavayi #include "cn66xx_device.h"
34f21fb3edSRaghu Vatsavayi #include "cn68xx_device.h"
3572c00912SRaghu Vatsavayi #include "cn23xx_pf_device.h"
36f21fb3edSRaghu Vatsavayi #include "liquidio_image.h"
37d4be8ebeSVijaya Mohan Guvva #include "lio_vf_rep.h"
38f21fb3edSRaghu Vatsavayi 
39f21fb3edSRaghu Vatsavayi MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
40f21fb3edSRaghu Vatsavayi MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Driver");
41f21fb3edSRaghu Vatsavayi MODULE_LICENSE("GPL");
42ea6404c8SDerek Chickles MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210SV_NAME
43ea6404c8SDerek Chickles 		"_" LIO_FW_NAME_TYPE_NIC LIO_FW_NAME_SUFFIX);
44ea6404c8SDerek Chickles MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210NV_NAME
45ea6404c8SDerek Chickles 		"_" LIO_FW_NAME_TYPE_NIC LIO_FW_NAME_SUFFIX);
46ea6404c8SDerek Chickles MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_410NV_NAME
47ea6404c8SDerek Chickles 		"_" LIO_FW_NAME_TYPE_NIC LIO_FW_NAME_SUFFIX);
48ea6404c8SDerek Chickles MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_23XX_NAME
49ea6404c8SDerek Chickles 		"_" LIO_FW_NAME_TYPE_NIC LIO_FW_NAME_SUFFIX);
50f21fb3edSRaghu Vatsavayi 
51f21fb3edSRaghu Vatsavayi static int ddr_timeout = 10000;
52f21fb3edSRaghu Vatsavayi module_param(ddr_timeout, int, 0644);
53f21fb3edSRaghu Vatsavayi MODULE_PARM_DESC(ddr_timeout,
54f21fb3edSRaghu Vatsavayi 		 "Number of milliseconds to wait for DDR initialization. 0 waits for ddr_timeout to be set to non-zero value before starting to check");
55f21fb3edSRaghu Vatsavayi 
56f21fb3edSRaghu Vatsavayi #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
57f21fb3edSRaghu Vatsavayi 
58f21fb3edSRaghu Vatsavayi static int debug = -1;
59f21fb3edSRaghu Vatsavayi module_param(debug, int, 0644);
60f21fb3edSRaghu Vatsavayi MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
61f21fb3edSRaghu Vatsavayi 
62088b8749SRick Farrington static char fw_type[LIO_MAX_FW_TYPE_LEN] = LIO_FW_NAME_TYPE_AUTO;
63d396179cSDerek Chickles module_param_string(fw_type, fw_type, sizeof(fw_type), 0444);
64088b8749SRick Farrington MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded (default is \"auto\"), which uses firmware in flash, if present, else loads \"nic\".");
65f21fb3edSRaghu Vatsavayi 
662470f3a2SIntiyaz Basha static u32 console_bitmask;
672470f3a2SIntiyaz Basha module_param(console_bitmask, int, 0644);
682470f3a2SIntiyaz Basha MODULE_PARM_DESC(console_bitmask,
692470f3a2SIntiyaz Basha 		 "Bitmask indicating which consoles have debug output redirected to syslog.");
702470f3a2SIntiyaz Basha 
712470f3a2SIntiyaz Basha /**
72d0ea5cbdSJesse Brandeburg  * octeon_console_debug_enabled - determines if a given console has debug enabled.
73d0ea5cbdSJesse Brandeburg  * @console: console to check
74d0ea5cbdSJesse Brandeburg  * Return:  1 = enabled. 0 otherwise
752470f3a2SIntiyaz Basha  */
octeon_console_debug_enabled(u32 console)76da1542b0SRick Farrington static int octeon_console_debug_enabled(u32 console)
772470f3a2SIntiyaz Basha {
782470f3a2SIntiyaz Basha 	return (console_bitmask >> (console)) & 0x1;
792470f3a2SIntiyaz Basha }
802470f3a2SIntiyaz Basha 
81f21fb3edSRaghu Vatsavayi /* Polling interval for determining when NIC application is alive */
82f21fb3edSRaghu Vatsavayi #define LIQUIDIO_STARTER_POLL_INTERVAL_MS 100
83f21fb3edSRaghu Vatsavayi 
84f21fb3edSRaghu Vatsavayi /* runtime link query interval */
85f21fb3edSRaghu Vatsavayi #define LIQUIDIO_LINK_QUERY_INTERVAL_MS         1000
86907aaa6bSVeerasenareddy Burru /* update localtime to octeon firmware every 60 seconds.
87907aaa6bSVeerasenareddy Burru  * make firmware to use same time reference, so that it will be easy to
88907aaa6bSVeerasenareddy Burru  * correlate firmware logged events/errors with host events, for debugging.
89907aaa6bSVeerasenareddy Burru  */
90907aaa6bSVeerasenareddy Burru #define LIO_SYNC_OCTEON_TIME_INTERVAL_MS 60000
91f21fb3edSRaghu Vatsavayi 
927481a857SNicholas Mc Guire /* time to wait for possible in-flight requests in milliseconds */
937481a857SNicholas Mc Guire #define WAIT_INFLIGHT_REQUEST	msecs_to_jiffies(1000)
947481a857SNicholas Mc Guire 
95f21fb3edSRaghu Vatsavayi struct oct_link_status_resp {
96f21fb3edSRaghu Vatsavayi 	u64 rh;
97f21fb3edSRaghu Vatsavayi 	struct oct_link_info link_info;
98f21fb3edSRaghu Vatsavayi 	u64 status;
99f21fb3edSRaghu Vatsavayi };
100f21fb3edSRaghu Vatsavayi 
101f21fb3edSRaghu Vatsavayi struct oct_timestamp_resp {
102f21fb3edSRaghu Vatsavayi 	u64 rh;
103f21fb3edSRaghu Vatsavayi 	u64 timestamp;
104f21fb3edSRaghu Vatsavayi 	u64 status;
105f21fb3edSRaghu Vatsavayi };
106f21fb3edSRaghu Vatsavayi 
107f21fb3edSRaghu Vatsavayi #define OCT_TIMESTAMP_RESP_SIZE (sizeof(struct oct_timestamp_resp))
108f21fb3edSRaghu Vatsavayi 
109f21fb3edSRaghu Vatsavayi union tx_info {
110f21fb3edSRaghu Vatsavayi 	u64 u64;
111f21fb3edSRaghu Vatsavayi 	struct {
112f21fb3edSRaghu Vatsavayi #ifdef __BIG_ENDIAN_BITFIELD
113f21fb3edSRaghu Vatsavayi 		u16 gso_size;
114f21fb3edSRaghu Vatsavayi 		u16 gso_segs;
115f21fb3edSRaghu Vatsavayi 		u32 reserved;
116f21fb3edSRaghu Vatsavayi #else
117f21fb3edSRaghu Vatsavayi 		u32 reserved;
118f21fb3edSRaghu Vatsavayi 		u16 gso_segs;
119f21fb3edSRaghu Vatsavayi 		u16 gso_size;
120f21fb3edSRaghu Vatsavayi #endif
121f21fb3edSRaghu Vatsavayi 	} s;
122f21fb3edSRaghu Vatsavayi };
123f21fb3edSRaghu Vatsavayi 
124d0ea5cbdSJesse Brandeburg /* Octeon device properties to be used by the NIC module.
125f21fb3edSRaghu Vatsavayi  * Each octeon device in the system will be represented
126f21fb3edSRaghu Vatsavayi  * by this structure in the NIC module.
127f21fb3edSRaghu Vatsavayi  */
128f21fb3edSRaghu Vatsavayi 
129f21fb3edSRaghu Vatsavayi #define OCTNIC_GSO_MAX_HEADER_SIZE 128
13072c00912SRaghu Vatsavayi #define OCTNIC_GSO_MAX_SIZE                                                    \
13172c00912SRaghu Vatsavayi 	(CN23XX_DEFAULT_INPUT_JABBER - OCTNIC_GSO_MAX_HEADER_SIZE)
132f21fb3edSRaghu Vatsavayi 
133f21fb3edSRaghu Vatsavayi struct handshake {
134f21fb3edSRaghu Vatsavayi 	struct completion init;
135f21fb3edSRaghu Vatsavayi 	struct completion started;
136f21fb3edSRaghu Vatsavayi 	struct pci_dev *pci_dev;
137f21fb3edSRaghu Vatsavayi 	int init_ok;
138f21fb3edSRaghu Vatsavayi 	int started_ok;
139f21fb3edSRaghu Vatsavayi };
140f21fb3edSRaghu Vatsavayi 
141ca6139ffSRaghu Vatsavayi #ifdef CONFIG_PCI_IOV
142ca6139ffSRaghu Vatsavayi static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs);
143ca6139ffSRaghu Vatsavayi #endif
144ca6139ffSRaghu Vatsavayi 
145da1542b0SRick Farrington static int octeon_dbg_console_print(struct octeon_device *oct, u32 console_num,
146da1542b0SRick Farrington 				    char *prefix, char *suffix);
147da1542b0SRick Farrington 
148f21fb3edSRaghu Vatsavayi static int octeon_device_init(struct octeon_device *);
14932581245SRaghu Vatsavayi static int liquidio_stop(struct net_device *netdev);
150f21fb3edSRaghu Vatsavayi static void liquidio_remove(struct pci_dev *pdev);
151f21fb3edSRaghu Vatsavayi static int liquidio_probe(struct pci_dev *pdev,
152f21fb3edSRaghu Vatsavayi 			  const struct pci_device_id *ent);
153bb54be58SFelix Manlunas static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
154bb54be58SFelix Manlunas 				      int linkstate);
155f21fb3edSRaghu Vatsavayi 
156f21fb3edSRaghu Vatsavayi static struct handshake handshake[MAX_OCTEON_DEVICES];
157f21fb3edSRaghu Vatsavayi static struct completion first_stage;
158f21fb3edSRaghu Vatsavayi 
octeon_droq_bh(struct tasklet_struct * t)159dfe4e612SAllen Pais static void octeon_droq_bh(struct tasklet_struct *t)
160f21fb3edSRaghu Vatsavayi {
161f21fb3edSRaghu Vatsavayi 	int q_no;
162f21fb3edSRaghu Vatsavayi 	int reschedule = 0;
163dfe4e612SAllen Pais 	struct octeon_device_priv *oct_priv = from_tasklet(oct_priv, t,
164dfe4e612SAllen Pais 							  droq_tasklet);
165dfe4e612SAllen Pais 	struct octeon_device *oct = oct_priv->dev;
166f21fb3edSRaghu Vatsavayi 
16763da8404SRaghu Vatsavayi 	for (q_no = 0; q_no < MAX_OCTEON_OUTPUT_QUEUES(oct); q_no++) {
168763185a3SRaghu Vatsavayi 		if (!(oct->io_qmask.oq & BIT_ULL(q_no)))
169f21fb3edSRaghu Vatsavayi 			continue;
170f21fb3edSRaghu Vatsavayi 		reschedule |= octeon_droq_process_packets(oct, oct->droq[q_no],
171f21fb3edSRaghu Vatsavayi 							  MAX_PACKET_BUDGET);
172cd8b1eb4SRaghu Vatsavayi 		lio_enable_irq(oct->droq[q_no], NULL);
1735b07aee1SRaghu Vatsavayi 
1745b07aee1SRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(oct) && oct->msix_on) {
1755b07aee1SRaghu Vatsavayi 			/* set time and cnt interrupt thresholds for this DROQ
1765b07aee1SRaghu Vatsavayi 			 * for NAPI
1775b07aee1SRaghu Vatsavayi 			 */
1785b07aee1SRaghu Vatsavayi 			int adjusted_q_no = q_no + oct->sriov_info.pf_srn;
1795b07aee1SRaghu Vatsavayi 
1805b07aee1SRaghu Vatsavayi 			octeon_write_csr64(
1815b07aee1SRaghu Vatsavayi 			    oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(adjusted_q_no),
1825b07aee1SRaghu Vatsavayi 			    0x5700000040ULL);
1835b07aee1SRaghu Vatsavayi 			octeon_write_csr64(
1845b07aee1SRaghu Vatsavayi 			    oct, CN23XX_SLI_OQ_PKTS_SENT(adjusted_q_no), 0);
1855b07aee1SRaghu Vatsavayi 		}
186f21fb3edSRaghu Vatsavayi 	}
187f21fb3edSRaghu Vatsavayi 
188f21fb3edSRaghu Vatsavayi 	if (reschedule)
189f21fb3edSRaghu Vatsavayi 		tasklet_schedule(&oct_priv->droq_tasklet);
190f21fb3edSRaghu Vatsavayi }
191f21fb3edSRaghu Vatsavayi 
lio_wait_for_oq_pkts(struct octeon_device * oct)1925b173cf9SRaghu Vatsavayi static int lio_wait_for_oq_pkts(struct octeon_device *oct)
193f21fb3edSRaghu Vatsavayi {
194f21fb3edSRaghu Vatsavayi 	struct octeon_device_priv *oct_priv = oct->priv;
195f21fb3edSRaghu Vatsavayi 	int retry = 100, pkt_cnt = 0, pending_pkts = 0;
196f21fb3edSRaghu Vatsavayi 	int i;
197f21fb3edSRaghu Vatsavayi 
198f21fb3edSRaghu Vatsavayi 	do {
199f21fb3edSRaghu Vatsavayi 		pending_pkts = 0;
200f21fb3edSRaghu Vatsavayi 
201f21fb3edSRaghu Vatsavayi 		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
20263da8404SRaghu Vatsavayi 			if (!(oct->io_qmask.oq & BIT_ULL(i)))
203763185a3SRaghu Vatsavayi 				continue;
204f21fb3edSRaghu Vatsavayi 			pkt_cnt += octeon_droq_check_hw_for_pkts(oct->droq[i]);
205a7d5a3dcSRaghu Vatsavayi 		}
206f21fb3edSRaghu Vatsavayi 		if (pkt_cnt > 0) {
207f21fb3edSRaghu Vatsavayi 			pending_pkts += pkt_cnt;
208f21fb3edSRaghu Vatsavayi 			tasklet_schedule(&oct_priv->droq_tasklet);
209f21fb3edSRaghu Vatsavayi 		}
210f21fb3edSRaghu Vatsavayi 		pkt_cnt = 0;
211f21fb3edSRaghu Vatsavayi 		schedule_timeout_uninterruptible(1);
212f21fb3edSRaghu Vatsavayi 
213f21fb3edSRaghu Vatsavayi 	} while (retry-- && pending_pkts);
214f21fb3edSRaghu Vatsavayi 
215f21fb3edSRaghu Vatsavayi 	return pkt_cnt;
216f21fb3edSRaghu Vatsavayi }
217f21fb3edSRaghu Vatsavayi 
218f21fb3edSRaghu Vatsavayi /**
219f21fb3edSRaghu Vatsavayi  * force_io_queues_off - Forces all IO queues off on a given device
220d0ea5cbdSJesse Brandeburg  * @oct: Pointer to Octeon device
221d0ea5cbdSJesse Brandeburg  */
force_io_queues_off(struct octeon_device * oct)222f21fb3edSRaghu Vatsavayi static void force_io_queues_off(struct octeon_device *oct)
223f21fb3edSRaghu Vatsavayi {
224f21fb3edSRaghu Vatsavayi 	if ((oct->chip_id == OCTEON_CN66XX) ||
225f21fb3edSRaghu Vatsavayi 	    (oct->chip_id == OCTEON_CN68XX)) {
226f21fb3edSRaghu Vatsavayi 		/* Reset the Enable bits for Input Queues. */
227f21fb3edSRaghu Vatsavayi 		octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
228f21fb3edSRaghu Vatsavayi 
229f21fb3edSRaghu Vatsavayi 		/* Reset the Enable bits for Output Queues. */
230f21fb3edSRaghu Vatsavayi 		octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
231f21fb3edSRaghu Vatsavayi 	}
232f21fb3edSRaghu Vatsavayi }
233f21fb3edSRaghu Vatsavayi 
234f21fb3edSRaghu Vatsavayi /**
235f21fb3edSRaghu Vatsavayi  * pcierror_quiesce_device - Cause device to go quiet so it can be safely removed/reset/etc
236d0ea5cbdSJesse Brandeburg  * @oct: Pointer to Octeon device
237d0ea5cbdSJesse Brandeburg  */
pcierror_quiesce_device(struct octeon_device * oct)238f21fb3edSRaghu Vatsavayi static inline void pcierror_quiesce_device(struct octeon_device *oct)
239f21fb3edSRaghu Vatsavayi {
240f21fb3edSRaghu Vatsavayi 	int i;
241f21fb3edSRaghu Vatsavayi 
242f21fb3edSRaghu Vatsavayi 	/* Disable the input and output queues now. No more packets will
243f21fb3edSRaghu Vatsavayi 	 * arrive from Octeon, but we should wait for all packet processing
244f21fb3edSRaghu Vatsavayi 	 * to finish.
245f21fb3edSRaghu Vatsavayi 	 */
246f21fb3edSRaghu Vatsavayi 	force_io_queues_off(oct);
247f21fb3edSRaghu Vatsavayi 
248f21fb3edSRaghu Vatsavayi 	/* To allow for in-flight requests */
249f21fb3edSRaghu Vatsavayi 	schedule_timeout_uninterruptible(WAIT_INFLIGHT_REQUEST);
2507481a857SNicholas Mc Guire 
251f21fb3edSRaghu Vatsavayi 	if (wait_for_pending_requests(oct))
252f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "There were pending requests\n");
253f21fb3edSRaghu Vatsavayi 
254f21fb3edSRaghu Vatsavayi 	/* Force all requests waiting to be fetched by OCTEON to complete. */
255f21fb3edSRaghu Vatsavayi 	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
25663da8404SRaghu Vatsavayi 		struct octeon_instr_queue *iq;
257f21fb3edSRaghu Vatsavayi 
258f21fb3edSRaghu Vatsavayi 		if (!(oct->io_qmask.iq & BIT_ULL(i)))
259763185a3SRaghu Vatsavayi 			continue;
260f21fb3edSRaghu Vatsavayi 		iq = oct->instr_queue[i];
261f21fb3edSRaghu Vatsavayi 
262f21fb3edSRaghu Vatsavayi 		if (atomic_read(&iq->instr_pending)) {
263f21fb3edSRaghu Vatsavayi 			spin_lock_bh(&iq->lock);
264f21fb3edSRaghu Vatsavayi 			iq->fill_cnt = 0;
265f21fb3edSRaghu Vatsavayi 			iq->octeon_read_index = iq->host_write_index;
266f21fb3edSRaghu Vatsavayi 			iq->stats.instr_processed +=
267f21fb3edSRaghu Vatsavayi 				atomic_read(&iq->instr_pending);
268f21fb3edSRaghu Vatsavayi 			lio_process_iq_request_list(oct, iq, 0);
2699a96bde4SRaghu Vatsavayi 			spin_unlock_bh(&iq->lock);
270f21fb3edSRaghu Vatsavayi 		}
271f21fb3edSRaghu Vatsavayi 	}
272f21fb3edSRaghu Vatsavayi 
273f21fb3edSRaghu Vatsavayi 	/* Force all pending ordered list requests to time out. */
274f21fb3edSRaghu Vatsavayi 	lio_process_ordered_list(oct, 1);
275f21fb3edSRaghu Vatsavayi 
276f21fb3edSRaghu Vatsavayi 	/* We do not need to wait for output queue packets to be processed. */
277f21fb3edSRaghu Vatsavayi }
278f21fb3edSRaghu Vatsavayi 
279f21fb3edSRaghu Vatsavayi /**
280f21fb3edSRaghu Vatsavayi  * cleanup_aer_uncorrect_error_status - Cleanup PCI AER uncorrectable error status
281d0ea5cbdSJesse Brandeburg  * @dev: Pointer to PCI device
282d0ea5cbdSJesse Brandeburg  */
cleanup_aer_uncorrect_error_status(struct pci_dev * dev)283f21fb3edSRaghu Vatsavayi static void cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
284f21fb3edSRaghu Vatsavayi {
285f21fb3edSRaghu Vatsavayi 	int pos = 0x100;
286f21fb3edSRaghu Vatsavayi 	u32 status, mask;
287f21fb3edSRaghu Vatsavayi 
288f21fb3edSRaghu Vatsavayi 	pr_info("%s :\n", __func__);
289f21fb3edSRaghu Vatsavayi 
290f21fb3edSRaghu Vatsavayi 	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
291f21fb3edSRaghu Vatsavayi 	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
292f21fb3edSRaghu Vatsavayi 	if (dev->error_state == pci_channel_io_normal)
293f21fb3edSRaghu Vatsavayi 		status &= ~mask;        /* Clear corresponding nonfatal bits */
294f21fb3edSRaghu Vatsavayi 	else
295f21fb3edSRaghu Vatsavayi 		status &= mask;         /* Clear corresponding fatal bits */
296f21fb3edSRaghu Vatsavayi 	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
297f21fb3edSRaghu Vatsavayi }
298f21fb3edSRaghu Vatsavayi 
299f21fb3edSRaghu Vatsavayi /**
300f21fb3edSRaghu Vatsavayi  * stop_pci_io - Stop all PCI IO to a given device
301d0ea5cbdSJesse Brandeburg  * @oct: Pointer to Octeon device
302d0ea5cbdSJesse Brandeburg  */
stop_pci_io(struct octeon_device * oct)303f21fb3edSRaghu Vatsavayi static void stop_pci_io(struct octeon_device *oct)
304f21fb3edSRaghu Vatsavayi {
305f21fb3edSRaghu Vatsavayi 	/* No more instructions will be forwarded. */
306f21fb3edSRaghu Vatsavayi 	atomic_set(&oct->status, OCT_DEV_IN_RESET);
307f21fb3edSRaghu Vatsavayi 
308f21fb3edSRaghu Vatsavayi 	pci_disable_device(oct->pci_dev);
309f21fb3edSRaghu Vatsavayi 
310f21fb3edSRaghu Vatsavayi 	/* Disable interrupts  */
311f21fb3edSRaghu Vatsavayi 	oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
3125b07aee1SRaghu Vatsavayi 
313f21fb3edSRaghu Vatsavayi 	pcierror_quiesce_device(oct);
314f21fb3edSRaghu Vatsavayi 
315f21fb3edSRaghu Vatsavayi 	/* Release the interrupt line */
316f21fb3edSRaghu Vatsavayi 	free_irq(oct->pci_dev->irq, oct);
317f21fb3edSRaghu Vatsavayi 
318f21fb3edSRaghu Vatsavayi 	if (oct->flags & LIO_FLAG_MSI_ENABLED)
319f21fb3edSRaghu Vatsavayi 		pci_disable_msi(oct->pci_dev);
320f21fb3edSRaghu Vatsavayi 
321f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
322f21fb3edSRaghu Vatsavayi 		lio_get_state_string(&oct->status));
323f21fb3edSRaghu Vatsavayi 
324f21fb3edSRaghu Vatsavayi 	/* making it a common function for all OCTEON models */
325f21fb3edSRaghu Vatsavayi 	cleanup_aer_uncorrect_error_status(oct->pci_dev);
326f21fb3edSRaghu Vatsavayi }
327f21fb3edSRaghu Vatsavayi 
328f21fb3edSRaghu Vatsavayi /**
329f21fb3edSRaghu Vatsavayi  * liquidio_pcie_error_detected - called when PCI error is detected
330d0ea5cbdSJesse Brandeburg  * @pdev: Pointer to PCI device
331d0ea5cbdSJesse Brandeburg  * @state: The current pci connection state
332d0ea5cbdSJesse Brandeburg  *
333f21fb3edSRaghu Vatsavayi  * This function is called after a PCI bus error affecting
334f21fb3edSRaghu Vatsavayi  * this device has been detected.
335f21fb3edSRaghu Vatsavayi  */
liquidio_pcie_error_detected(struct pci_dev * pdev,pci_channel_state_t state)336f21fb3edSRaghu Vatsavayi static pci_ers_result_t liquidio_pcie_error_detected(struct pci_dev *pdev,
337f21fb3edSRaghu Vatsavayi 						     pci_channel_state_t state)
338f21fb3edSRaghu Vatsavayi {
339f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = pci_get_drvdata(pdev);
340f21fb3edSRaghu Vatsavayi 
341f21fb3edSRaghu Vatsavayi 	/* Non-correctable Non-fatal errors */
342f21fb3edSRaghu Vatsavayi 	if (state == pci_channel_io_normal) {
343f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Non-correctable non-fatal error reported:\n");
344f21fb3edSRaghu Vatsavayi 		cleanup_aer_uncorrect_error_status(oct->pci_dev);
345f21fb3edSRaghu Vatsavayi 		return PCI_ERS_RESULT_CAN_RECOVER;
346f21fb3edSRaghu Vatsavayi 	}
347f21fb3edSRaghu Vatsavayi 
348f21fb3edSRaghu Vatsavayi 	/* Non-correctable Fatal errors */
349f21fb3edSRaghu Vatsavayi 	dev_err(&oct->pci_dev->dev, "Non-correctable FATAL reported by PCI AER driver\n");
350f21fb3edSRaghu Vatsavayi 	stop_pci_io(oct);
351f21fb3edSRaghu Vatsavayi 
352f21fb3edSRaghu Vatsavayi 	/* Always return a DISCONNECT. There is no support for recovery but only
353f21fb3edSRaghu Vatsavayi 	 * for a clean shutdown.
354f21fb3edSRaghu Vatsavayi 	 */
355f21fb3edSRaghu Vatsavayi 	return PCI_ERS_RESULT_DISCONNECT;
356f21fb3edSRaghu Vatsavayi }
357f21fb3edSRaghu Vatsavayi 
358f21fb3edSRaghu Vatsavayi /**
359f21fb3edSRaghu Vatsavayi  * liquidio_pcie_mmio_enabled - mmio handler
360d0ea5cbdSJesse Brandeburg  * @pdev: Pointer to PCI device
361d0ea5cbdSJesse Brandeburg  */
liquidio_pcie_mmio_enabled(struct pci_dev __maybe_unused * pdev)362f21fb3edSRaghu Vatsavayi static pci_ers_result_t liquidio_pcie_mmio_enabled(struct pci_dev __maybe_unused *pdev)
363d0ea5cbdSJesse Brandeburg {
364f21fb3edSRaghu Vatsavayi 	/* We should never hit this since we never ask for a reset for a Fatal
365f21fb3edSRaghu Vatsavayi 	 * Error. We always return DISCONNECT in io_error above.
366f21fb3edSRaghu Vatsavayi 	 * But play safe and return RECOVERED for now.
367f21fb3edSRaghu Vatsavayi 	 */
368f21fb3edSRaghu Vatsavayi 	return PCI_ERS_RESULT_RECOVERED;
369f21fb3edSRaghu Vatsavayi }
370f21fb3edSRaghu Vatsavayi 
371f21fb3edSRaghu Vatsavayi /**
372f21fb3edSRaghu Vatsavayi  * liquidio_pcie_slot_reset - called after the pci bus has been reset.
373d0ea5cbdSJesse Brandeburg  * @pdev: Pointer to PCI device
374d0ea5cbdSJesse Brandeburg  *
375f21fb3edSRaghu Vatsavayi  * Restart the card from scratch, as if from a cold-boot. Implementation
376f21fb3edSRaghu Vatsavayi  * resembles the first-half of the octeon_resume routine.
377f21fb3edSRaghu Vatsavayi  */
liquidio_pcie_slot_reset(struct pci_dev __maybe_unused * pdev)378f21fb3edSRaghu Vatsavayi static pci_ers_result_t liquidio_pcie_slot_reset(struct pci_dev __maybe_unused *pdev)
379d0ea5cbdSJesse Brandeburg {
380f21fb3edSRaghu Vatsavayi 	/* We should never hit this since we never ask for a reset for a Fatal
381f21fb3edSRaghu Vatsavayi 	 * Error. We always return DISCONNECT in io_error above.
382f21fb3edSRaghu Vatsavayi 	 * But play safe and return RECOVERED for now.
383f21fb3edSRaghu Vatsavayi 	 */
384f21fb3edSRaghu Vatsavayi 	return PCI_ERS_RESULT_RECOVERED;
385f21fb3edSRaghu Vatsavayi }
386f21fb3edSRaghu Vatsavayi 
387f21fb3edSRaghu Vatsavayi /**
388f21fb3edSRaghu Vatsavayi  * liquidio_pcie_resume - called when traffic can start flowing again.
389d0ea5cbdSJesse Brandeburg  * @pdev: Pointer to PCI device
390d0ea5cbdSJesse Brandeburg  *
391f21fb3edSRaghu Vatsavayi  * This callback is called when the error recovery driver tells us that
392f21fb3edSRaghu Vatsavayi  * its OK to resume normal operation. Implementation resembles the
393f21fb3edSRaghu Vatsavayi  * second-half of the octeon_resume routine.
394f21fb3edSRaghu Vatsavayi  */
liquidio_pcie_resume(struct pci_dev __maybe_unused * pdev)395f21fb3edSRaghu Vatsavayi static void liquidio_pcie_resume(struct pci_dev __maybe_unused *pdev)
396d0ea5cbdSJesse Brandeburg {
397f21fb3edSRaghu Vatsavayi 	/* Nothing to be done here. */
398f21fb3edSRaghu Vatsavayi }
399f21fb3edSRaghu Vatsavayi 
400f21fb3edSRaghu Vatsavayi #define liquidio_suspend NULL
4011c2e4839SVaibhav Gupta #define liquidio_resume NULL
4021c2e4839SVaibhav Gupta 
403f21fb3edSRaghu Vatsavayi /* For PCI-E Advanced Error Recovery (AER) Interface */
404f21fb3edSRaghu Vatsavayi static const struct pci_error_handlers liquidio_err_handler = {
405166e2362SJulia Lawall 	.error_detected = liquidio_pcie_error_detected,
406f21fb3edSRaghu Vatsavayi 	.mmio_enabled	= liquidio_pcie_mmio_enabled,
407f21fb3edSRaghu Vatsavayi 	.slot_reset	= liquidio_pcie_slot_reset,
408f21fb3edSRaghu Vatsavayi 	.resume		= liquidio_pcie_resume,
409f21fb3edSRaghu Vatsavayi };
410f21fb3edSRaghu Vatsavayi 
411f21fb3edSRaghu Vatsavayi static const struct pci_device_id liquidio_pci_tbl[] = {
412f21fb3edSRaghu Vatsavayi 	{       /* 68xx */
413f21fb3edSRaghu Vatsavayi 		PCI_VENDOR_ID_CAVIUM, 0x91, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
414f21fb3edSRaghu Vatsavayi 	},
415f21fb3edSRaghu Vatsavayi 	{       /* 66xx */
416f21fb3edSRaghu Vatsavayi 		PCI_VENDOR_ID_CAVIUM, 0x92, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
417f21fb3edSRaghu Vatsavayi 	},
418f21fb3edSRaghu Vatsavayi 	{       /* 23xx pf */
419e86b1ab6SRaghu Vatsavayi 		PCI_VENDOR_ID_CAVIUM, 0x9702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
420e86b1ab6SRaghu Vatsavayi 	},
421e86b1ab6SRaghu Vatsavayi 	{
422f21fb3edSRaghu Vatsavayi 		0, 0, 0, 0, 0, 0, 0
423f21fb3edSRaghu Vatsavayi 	}
424f21fb3edSRaghu Vatsavayi };
425f21fb3edSRaghu Vatsavayi MODULE_DEVICE_TABLE(pci, liquidio_pci_tbl);
426f21fb3edSRaghu Vatsavayi 
427f21fb3edSRaghu Vatsavayi static SIMPLE_DEV_PM_OPS(liquidio_pm_ops, liquidio_suspend, liquidio_resume);
4281c2e4839SVaibhav Gupta 
4291c2e4839SVaibhav Gupta static struct pci_driver liquidio_pci_driver = {
430f21fb3edSRaghu Vatsavayi 	.name		= "LiquidIO",
431f21fb3edSRaghu Vatsavayi 	.id_table	= liquidio_pci_tbl,
432f21fb3edSRaghu Vatsavayi 	.probe		= liquidio_probe,
433f21fb3edSRaghu Vatsavayi 	.remove		= liquidio_remove,
434f21fb3edSRaghu Vatsavayi 	.err_handler	= &liquidio_err_handler,    /* For AER */
435f21fb3edSRaghu Vatsavayi 	.driver.pm	= &liquidio_pm_ops,
4361c2e4839SVaibhav Gupta #ifdef CONFIG_PCI_IOV
437ca6139ffSRaghu Vatsavayi 	.sriov_configure = liquidio_enable_sriov,
438ca6139ffSRaghu Vatsavayi #endif
439ca6139ffSRaghu Vatsavayi };
440f21fb3edSRaghu Vatsavayi 
441f21fb3edSRaghu Vatsavayi /**
442f21fb3edSRaghu Vatsavayi  * liquidio_init_pci - register PCI driver
443d0ea5cbdSJesse Brandeburg  */
liquidio_init_pci(void)444f21fb3edSRaghu Vatsavayi static int liquidio_init_pci(void)
445f21fb3edSRaghu Vatsavayi {
446f21fb3edSRaghu Vatsavayi 	return pci_register_driver(&liquidio_pci_driver);
447f21fb3edSRaghu Vatsavayi }
448f21fb3edSRaghu Vatsavayi 
449f21fb3edSRaghu Vatsavayi /**
450f21fb3edSRaghu Vatsavayi  * liquidio_deinit_pci - unregister PCI driver
451d0ea5cbdSJesse Brandeburg  */
liquidio_deinit_pci(void)452f21fb3edSRaghu Vatsavayi static void liquidio_deinit_pci(void)
453f21fb3edSRaghu Vatsavayi {
454f21fb3edSRaghu Vatsavayi 	pci_unregister_driver(&liquidio_pci_driver);
455f21fb3edSRaghu Vatsavayi }
456f21fb3edSRaghu Vatsavayi 
457f21fb3edSRaghu Vatsavayi /**
458f21fb3edSRaghu Vatsavayi  * check_txq_status - Check Tx queue status, and take appropriate action
459d0ea5cbdSJesse Brandeburg  * @lio: per-network private data
460d0ea5cbdSJesse Brandeburg  * Return: 0 if full, number of queues woken up otherwise
461d0ea5cbdSJesse Brandeburg  */
check_txq_status(struct lio * lio)462f21fb3edSRaghu Vatsavayi static inline int check_txq_status(struct lio *lio)
463f21fb3edSRaghu Vatsavayi {
464f21fb3edSRaghu Vatsavayi 	int numqs = lio->netdev->real_num_tx_queues;
465c33c9973SIntiyaz Basha 	int ret_val = 0;
4662a2fabafSIntiyaz Basha 	int q, iq;
4672a2fabafSIntiyaz Basha 
468f21fb3edSRaghu Vatsavayi 	/* check each sub-queue state */
469f21fb3edSRaghu Vatsavayi 	for (q = 0; q < numqs; q++) {
470f21fb3edSRaghu Vatsavayi 		iq = lio->linfo.txpciq[q %
47126236fa9SRaghu Vatsavayi 			lio->oct_dev->num_iqs].s.q_no;
472a82457f1SIntiyaz Basha 		if (octnet_iq_is_full(lio->oct_dev, iq))
473f21fb3edSRaghu Vatsavayi 			continue;
474f21fb3edSRaghu Vatsavayi 		if (__netif_subqueue_stopped(lio->netdev, q)) {
47526236fa9SRaghu Vatsavayi 			netif_wake_subqueue(lio->netdev, q);
476dd69debcSIntiyaz Basha 			INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq,
4771f164717SRaghu Vatsavayi 						  tx_restart, 1);
4781f164717SRaghu Vatsavayi 			ret_val++;
479f21fb3edSRaghu Vatsavayi 		}
480f21fb3edSRaghu Vatsavayi 	}
48126236fa9SRaghu Vatsavayi 
4822a2fabafSIntiyaz Basha 	return ret_val;
483f21fb3edSRaghu Vatsavayi }
484f21fb3edSRaghu Vatsavayi 
485f21fb3edSRaghu Vatsavayi /**
486f21fb3edSRaghu Vatsavayi  * print_link_info -  Print link information
487d0ea5cbdSJesse Brandeburg  * @netdev: network device
488d0ea5cbdSJesse Brandeburg  */
print_link_info(struct net_device * netdev)489f21fb3edSRaghu Vatsavayi static void print_link_info(struct net_device *netdev)
490f21fb3edSRaghu Vatsavayi {
491f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
492f21fb3edSRaghu Vatsavayi 
493f21fb3edSRaghu Vatsavayi 	if (!ifstate_check(lio, LIO_IFSTATE_RESETTING) &&
494d18ca7dfSIntiyaz Basha 	    ifstate_check(lio, LIO_IFSTATE_REGISTERED)) {
495d18ca7dfSIntiyaz Basha 		struct oct_link_info *linfo = &lio->linfo;
496f21fb3edSRaghu Vatsavayi 
497f21fb3edSRaghu Vatsavayi 		if (linfo->link.s.link_up) {
4980cece6c5SRaghu Vatsavayi 			netif_info(lio, link, lio->netdev, "%d Mbps %s Duplex UP\n",
499f21fb3edSRaghu Vatsavayi 				   linfo->link.s.speed,
500f21fb3edSRaghu Vatsavayi 				   (linfo->link.s.duplex) ? "Full" : "Half");
501f21fb3edSRaghu Vatsavayi 		} else {
502f21fb3edSRaghu Vatsavayi 			netif_info(lio, link, lio->netdev, "Link Down\n");
503f21fb3edSRaghu Vatsavayi 		}
504f21fb3edSRaghu Vatsavayi 	}
505f21fb3edSRaghu Vatsavayi }
506f21fb3edSRaghu Vatsavayi 
507f21fb3edSRaghu Vatsavayi /**
508f21fb3edSRaghu Vatsavayi  * octnet_link_status_change - Routine to notify MTU change
509d0ea5cbdSJesse Brandeburg  * @work: work_struct data structure
510d0ea5cbdSJesse Brandeburg  */
octnet_link_status_change(struct work_struct * work)5117b6b6c95SRaghu Vatsavayi static void octnet_link_status_change(struct work_struct *work)
5127b6b6c95SRaghu Vatsavayi {
5137b6b6c95SRaghu Vatsavayi 	struct cavium_wk *wk = (struct cavium_wk *)work;
5147b6b6c95SRaghu Vatsavayi 	struct lio *lio = (struct lio *)wk->ctxptr;
5157b6b6c95SRaghu Vatsavayi 
5167b6b6c95SRaghu Vatsavayi 	/* lio->linfo.link.s.mtu always contains max MTU of the lio interface.
51787a7c4b3SVeerasenareddy Burru 	 * this API is invoked only when new max-MTU of the interface is
51887a7c4b3SVeerasenareddy Burru 	 * less than current MTU.
51987a7c4b3SVeerasenareddy Burru 	 */
52087a7c4b3SVeerasenareddy Burru 	rtnl_lock();
5217b6b6c95SRaghu Vatsavayi 	dev_set_mtu(lio->netdev, lio->linfo.link.s.mtu);
52287a7c4b3SVeerasenareddy Burru 	rtnl_unlock();
5237b6b6c95SRaghu Vatsavayi }
5247b6b6c95SRaghu Vatsavayi 
5257b6b6c95SRaghu Vatsavayi /**
5267b6b6c95SRaghu Vatsavayi  * setup_link_status_change_wq - Sets up the mtu status change work
527d0ea5cbdSJesse Brandeburg  * @netdev: network device
528d0ea5cbdSJesse Brandeburg  */
setup_link_status_change_wq(struct net_device * netdev)5297b6b6c95SRaghu Vatsavayi static inline int setup_link_status_change_wq(struct net_device *netdev)
5307b6b6c95SRaghu Vatsavayi {
5317b6b6c95SRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
5327b6b6c95SRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
5337b6b6c95SRaghu Vatsavayi 
5347b6b6c95SRaghu Vatsavayi 	lio->link_status_wq.wq = alloc_workqueue("link-status",
5357b6b6c95SRaghu Vatsavayi 						 WQ_MEM_RECLAIM, 0);
5367b6b6c95SRaghu Vatsavayi 	if (!lio->link_status_wq.wq) {
5377b6b6c95SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "unable to create cavium link status wq\n");
5387b6b6c95SRaghu Vatsavayi 		return -1;
5397b6b6c95SRaghu Vatsavayi 	}
5407b6b6c95SRaghu Vatsavayi 	INIT_DELAYED_WORK(&lio->link_status_wq.wk.work,
5417b6b6c95SRaghu Vatsavayi 			  octnet_link_status_change);
5427b6b6c95SRaghu Vatsavayi 	lio->link_status_wq.wk.ctxptr = lio;
5437b6b6c95SRaghu Vatsavayi 
5447b6b6c95SRaghu Vatsavayi 	return 0;
5457b6b6c95SRaghu Vatsavayi }
5467b6b6c95SRaghu Vatsavayi 
cleanup_link_status_change_wq(struct net_device * netdev)5477b6b6c95SRaghu Vatsavayi static inline void cleanup_link_status_change_wq(struct net_device *netdev)
5487b6b6c95SRaghu Vatsavayi {
5497b6b6c95SRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
5507b6b6c95SRaghu Vatsavayi 
5517b6b6c95SRaghu Vatsavayi 	if (lio->link_status_wq.wq) {
5527b6b6c95SRaghu Vatsavayi 		cancel_delayed_work_sync(&lio->link_status_wq.wk.work);
5537b6b6c95SRaghu Vatsavayi 		destroy_workqueue(lio->link_status_wq.wq);
5547b6b6c95SRaghu Vatsavayi 	}
5557b6b6c95SRaghu Vatsavayi }
5567b6b6c95SRaghu Vatsavayi 
5577b6b6c95SRaghu Vatsavayi /**
5587b6b6c95SRaghu Vatsavayi  * update_link_status - Update link status
559d0ea5cbdSJesse Brandeburg  * @netdev: network device
560d0ea5cbdSJesse Brandeburg  * @ls: link status structure
561d0ea5cbdSJesse Brandeburg  *
562f21fb3edSRaghu Vatsavayi  * Called on receipt of a link status response from the core application to
563f21fb3edSRaghu Vatsavayi  * update each interface's link status.
564f21fb3edSRaghu Vatsavayi  */
update_link_status(struct net_device * netdev,union oct_link_status * ls)565f21fb3edSRaghu Vatsavayi static inline void update_link_status(struct net_device *netdev,
566f21fb3edSRaghu Vatsavayi 				      union oct_link_status *ls)
567f21fb3edSRaghu Vatsavayi {
568f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
569f21fb3edSRaghu Vatsavayi 	int changed = (lio->linfo.link.u64 != ls->u64);
5700cece6c5SRaghu Vatsavayi 	int current_max_mtu = lio->linfo.link.s.mtu;
57187a7c4b3SVeerasenareddy Burru 	struct octeon_device *oct = lio->oct_dev;
57287a7c4b3SVeerasenareddy Burru 
573f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct->pci_dev->dev, "%s: lio->linfo.link.u64=%llx, ls->u64=%llx\n",
57487a7c4b3SVeerasenareddy Burru 		__func__, lio->linfo.link.u64, ls->u64);
57587a7c4b3SVeerasenareddy Burru 	lio->linfo.link.u64 = ls->u64;
576f21fb3edSRaghu Vatsavayi 
577f21fb3edSRaghu Vatsavayi 	if ((lio->intf_open) && (changed)) {
5780cece6c5SRaghu Vatsavayi 		print_link_info(netdev);
579f21fb3edSRaghu Vatsavayi 		lio->link_changes++;
5800cece6c5SRaghu Vatsavayi 
581f21fb3edSRaghu Vatsavayi 		if (lio->linfo.link.s.link_up) {
5820cece6c5SRaghu Vatsavayi 			dev_dbg(&oct->pci_dev->dev, "%s: link_up", __func__);
58387a7c4b3SVeerasenareddy Burru 			netif_carrier_on(netdev);
584f21fb3edSRaghu Vatsavayi 			wake_txqs(netdev);
585a96d8ad3SIntiyaz Basha 		} else {
586f21fb3edSRaghu Vatsavayi 			dev_dbg(&oct->pci_dev->dev, "%s: link_off", __func__);
58787a7c4b3SVeerasenareddy Burru 			netif_carrier_off(netdev);
588f21fb3edSRaghu Vatsavayi 			stop_txqs(netdev);
589736b7ea5SIntiyaz Basha 		}
590f21fb3edSRaghu Vatsavayi 		if (lio->linfo.link.s.mtu != current_max_mtu) {
59187a7c4b3SVeerasenareddy Burru 			netif_info(lio, probe, lio->netdev, "Max MTU changed from %d to %d\n",
59287a7c4b3SVeerasenareddy Burru 				   current_max_mtu, lio->linfo.link.s.mtu);
59387a7c4b3SVeerasenareddy Burru 			netdev->max_mtu = lio->linfo.link.s.mtu;
59487a7c4b3SVeerasenareddy Burru 		}
59587a7c4b3SVeerasenareddy Burru 		if (lio->linfo.link.s.mtu < netdev->mtu) {
59687a7c4b3SVeerasenareddy Burru 			dev_warn(&oct->pci_dev->dev,
59787a7c4b3SVeerasenareddy Burru 				 "Current MTU is higher than new max MTU; Reducing the current mtu from %d to %d\n",
59887a7c4b3SVeerasenareddy Burru 				     netdev->mtu, lio->linfo.link.s.mtu);
59987a7c4b3SVeerasenareddy Burru 			queue_delayed_work(lio->link_status_wq.wq,
60087a7c4b3SVeerasenareddy Burru 					   &lio->link_status_wq.wk.work, 0);
60187a7c4b3SVeerasenareddy Burru 		}
60287a7c4b3SVeerasenareddy Burru 	}
603f21fb3edSRaghu Vatsavayi }
604f21fb3edSRaghu Vatsavayi 
605f21fb3edSRaghu Vatsavayi /**
606907aaa6bSVeerasenareddy Burru  * lio_sync_octeon_time - send latest localtime to octeon firmware so that
607907aaa6bSVeerasenareddy Burru  * firmware will correct it's time, in case there is a time skew
608907aaa6bSVeerasenareddy Burru  *
609907aaa6bSVeerasenareddy Burru  * @work: work scheduled to send time update to octeon firmware
610907aaa6bSVeerasenareddy Burru  **/
lio_sync_octeon_time(struct work_struct * work)611907aaa6bSVeerasenareddy Burru static void lio_sync_octeon_time(struct work_struct *work)
612907aaa6bSVeerasenareddy Burru {
613907aaa6bSVeerasenareddy Burru 	struct cavium_wk *wk = (struct cavium_wk *)work;
614907aaa6bSVeerasenareddy Burru 	struct lio *lio = (struct lio *)wk->ctxptr;
615907aaa6bSVeerasenareddy Burru 	struct octeon_device *oct = lio->oct_dev;
616907aaa6bSVeerasenareddy Burru 	struct octeon_soft_command *sc;
617907aaa6bSVeerasenareddy Burru 	struct timespec64 ts;
618907aaa6bSVeerasenareddy Burru 	struct lio_time *lt;
619907aaa6bSVeerasenareddy Burru 	int ret;
620907aaa6bSVeerasenareddy Burru 
621907aaa6bSVeerasenareddy Burru 	sc = octeon_alloc_soft_command(oct, sizeof(struct lio_time), 16, 0);
62264fecd3eSFelix Manlunas 	if (!sc) {
623907aaa6bSVeerasenareddy Burru 		dev_err(&oct->pci_dev->dev,
624907aaa6bSVeerasenareddy Burru 			"Failed to sync time to octeon: soft command allocation failed\n");
625907aaa6bSVeerasenareddy Burru 		return;
626907aaa6bSVeerasenareddy Burru 	}
627907aaa6bSVeerasenareddy Burru 
628907aaa6bSVeerasenareddy Burru 	lt = (struct lio_time *)sc->virtdptr;
629907aaa6bSVeerasenareddy Burru 
630907aaa6bSVeerasenareddy Burru 	/* Get time of the day */
631907aaa6bSVeerasenareddy Burru 	ktime_get_real_ts64(&ts);
63244c58899SArnd Bergmann 	lt->sec = ts.tv_sec;
633907aaa6bSVeerasenareddy Burru 	lt->nsec = ts.tv_nsec;
634907aaa6bSVeerasenareddy Burru 	octeon_swap_8B_data((u64 *)lt, (sizeof(struct lio_time)) / 8);
635907aaa6bSVeerasenareddy Burru 
636907aaa6bSVeerasenareddy Burru 	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
637907aaa6bSVeerasenareddy Burru 	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
638907aaa6bSVeerasenareddy Burru 				    OPCODE_NIC_SYNC_OCTEON_TIME, 0, 0, 0);
639907aaa6bSVeerasenareddy Burru 
640907aaa6bSVeerasenareddy Burru 	init_completion(&sc->complete);
64164fecd3eSFelix Manlunas 	sc->sc_status = OCTEON_REQUEST_PENDING;
64264fecd3eSFelix Manlunas 
643907aaa6bSVeerasenareddy Burru 	ret = octeon_send_soft_command(oct, sc);
644907aaa6bSVeerasenareddy Burru 	if (ret == IQ_SEND_FAILED) {
645907aaa6bSVeerasenareddy Burru 		dev_err(&oct->pci_dev->dev,
646907aaa6bSVeerasenareddy Burru 			"Failed to sync time to octeon: failed to send soft command\n");
647907aaa6bSVeerasenareddy Burru 		octeon_free_soft_command(oct, sc);
648907aaa6bSVeerasenareddy Burru 	} else {
64964fecd3eSFelix Manlunas 		WRITE_ONCE(sc->caller_is_done, true);
65064fecd3eSFelix Manlunas 	}
651907aaa6bSVeerasenareddy Burru 
652907aaa6bSVeerasenareddy Burru 	queue_delayed_work(lio->sync_octeon_time_wq.wq,
653907aaa6bSVeerasenareddy Burru 			   &lio->sync_octeon_time_wq.wk.work,
654907aaa6bSVeerasenareddy Burru 			   msecs_to_jiffies(LIO_SYNC_OCTEON_TIME_INTERVAL_MS));
655907aaa6bSVeerasenareddy Burru }
656907aaa6bSVeerasenareddy Burru 
657907aaa6bSVeerasenareddy Burru /**
658907aaa6bSVeerasenareddy Burru  * setup_sync_octeon_time_wq - prepare work to periodically update local time to octeon firmware
659d0ea5cbdSJesse Brandeburg  *
660907aaa6bSVeerasenareddy Burru  * @netdev: network device which should send time update to firmware
661d0ea5cbdSJesse Brandeburg  **/
setup_sync_octeon_time_wq(struct net_device * netdev)662907aaa6bSVeerasenareddy Burru static inline int setup_sync_octeon_time_wq(struct net_device *netdev)
663907aaa6bSVeerasenareddy Burru {
664907aaa6bSVeerasenareddy Burru 	struct lio *lio = GET_LIO(netdev);
665907aaa6bSVeerasenareddy Burru 	struct octeon_device *oct = lio->oct_dev;
666907aaa6bSVeerasenareddy Burru 
667907aaa6bSVeerasenareddy Burru 	lio->sync_octeon_time_wq.wq =
668907aaa6bSVeerasenareddy Burru 		alloc_workqueue("update-octeon-time", WQ_MEM_RECLAIM, 0);
669907aaa6bSVeerasenareddy Burru 	if (!lio->sync_octeon_time_wq.wq) {
670907aaa6bSVeerasenareddy Burru 		dev_err(&oct->pci_dev->dev, "Unable to create wq to update octeon time\n");
671907aaa6bSVeerasenareddy Burru 		return -1;
672907aaa6bSVeerasenareddy Burru 	}
673907aaa6bSVeerasenareddy Burru 	INIT_DELAYED_WORK(&lio->sync_octeon_time_wq.wk.work,
674907aaa6bSVeerasenareddy Burru 			  lio_sync_octeon_time);
675907aaa6bSVeerasenareddy Burru 	lio->sync_octeon_time_wq.wk.ctxptr = lio;
676907aaa6bSVeerasenareddy Burru 	queue_delayed_work(lio->sync_octeon_time_wq.wq,
677907aaa6bSVeerasenareddy Burru 			   &lio->sync_octeon_time_wq.wk.work,
678907aaa6bSVeerasenareddy Burru 			   msecs_to_jiffies(LIO_SYNC_OCTEON_TIME_INTERVAL_MS));
679907aaa6bSVeerasenareddy Burru 
680907aaa6bSVeerasenareddy Burru 	return 0;
681907aaa6bSVeerasenareddy Burru }
682907aaa6bSVeerasenareddy Burru 
683907aaa6bSVeerasenareddy Burru /**
684907aaa6bSVeerasenareddy Burru  * cleanup_sync_octeon_time_wq - destroy wq
685d0ea5cbdSJesse Brandeburg  *
686907aaa6bSVeerasenareddy Burru  * @netdev: network device which should send time update to firmware
687d0ea5cbdSJesse Brandeburg  *
688d0ea5cbdSJesse Brandeburg  * Stop scheduling and destroy the work created to periodically update local
689d0ea5cbdSJesse Brandeburg  * time to octeon firmware.
690d0ea5cbdSJesse Brandeburg  **/
cleanup_sync_octeon_time_wq(struct net_device * netdev)691907aaa6bSVeerasenareddy Burru static inline void cleanup_sync_octeon_time_wq(struct net_device *netdev)
692907aaa6bSVeerasenareddy Burru {
693907aaa6bSVeerasenareddy Burru 	struct lio *lio = GET_LIO(netdev);
694907aaa6bSVeerasenareddy Burru 	struct cavium_wq *time_wq = &lio->sync_octeon_time_wq;
695907aaa6bSVeerasenareddy Burru 
696907aaa6bSVeerasenareddy Burru 	if (time_wq->wq) {
697907aaa6bSVeerasenareddy Burru 		cancel_delayed_work_sync(&time_wq->wk.work);
698907aaa6bSVeerasenareddy Burru 		destroy_workqueue(time_wq->wq);
699907aaa6bSVeerasenareddy Burru 	}
700907aaa6bSVeerasenareddy Burru }
701907aaa6bSVeerasenareddy Burru 
get_other_octeon_device(struct octeon_device * oct)702907aaa6bSVeerasenareddy Burru static struct octeon_device *get_other_octeon_device(struct octeon_device *oct)
703bb54be58SFelix Manlunas {
704bb54be58SFelix Manlunas 	struct octeon_device *other_oct;
705bb54be58SFelix Manlunas 
706bb54be58SFelix Manlunas 	other_oct = lio_get_device(oct->octeon_id + 1);
707bb54be58SFelix Manlunas 
708bb54be58SFelix Manlunas 	if (other_oct && other_oct->pci_dev) {
709bb54be58SFelix Manlunas 		int oct_busnum, other_oct_busnum;
710bb54be58SFelix Manlunas 
711bb54be58SFelix Manlunas 		oct_busnum = oct->pci_dev->bus->number;
712bb54be58SFelix Manlunas 		other_oct_busnum = other_oct->pci_dev->bus->number;
713bb54be58SFelix Manlunas 
714bb54be58SFelix Manlunas 		if (oct_busnum == other_oct_busnum) {
715bb54be58SFelix Manlunas 			int oct_slot, other_oct_slot;
716bb54be58SFelix Manlunas 
717bb54be58SFelix Manlunas 			oct_slot = PCI_SLOT(oct->pci_dev->devfn);
718bb54be58SFelix Manlunas 			other_oct_slot = PCI_SLOT(other_oct->pci_dev->devfn);
719bb54be58SFelix Manlunas 
720bb54be58SFelix Manlunas 			if (oct_slot == other_oct_slot)
721bb54be58SFelix Manlunas 				return other_oct;
722bb54be58SFelix Manlunas 		}
723bb54be58SFelix Manlunas 	}
724bb54be58SFelix Manlunas 
725bb54be58SFelix Manlunas 	return NULL;
726bb54be58SFelix Manlunas }
727bb54be58SFelix Manlunas 
disable_all_vf_links(struct octeon_device * oct)728bb54be58SFelix Manlunas static void disable_all_vf_links(struct octeon_device *oct)
729bb54be58SFelix Manlunas {
730bb54be58SFelix Manlunas 	struct net_device *netdev;
731bb54be58SFelix Manlunas 	int max_vfs, vf, i;
732bb54be58SFelix Manlunas 
733bb54be58SFelix Manlunas 	if (!oct)
734bb54be58SFelix Manlunas 		return;
735bb54be58SFelix Manlunas 
736bb54be58SFelix Manlunas 	max_vfs = oct->sriov_info.max_vfs;
737bb54be58SFelix Manlunas 
738bb54be58SFelix Manlunas 	for (i = 0; i < oct->ifcount; i++) {
739bb54be58SFelix Manlunas 		netdev = oct->props[i].netdev;
740bb54be58SFelix Manlunas 		if (!netdev)
741bb54be58SFelix Manlunas 			continue;
742bb54be58SFelix Manlunas 
743bb54be58SFelix Manlunas 		for (vf = 0; vf < max_vfs; vf++)
744bb54be58SFelix Manlunas 			liquidio_set_vf_link_state(netdev, vf,
745bb54be58SFelix Manlunas 						   IFLA_VF_LINK_STATE_DISABLE);
746bb54be58SFelix Manlunas 	}
747bb54be58SFelix Manlunas }
748bb54be58SFelix Manlunas 
liquidio_watchdog(void * param)749bb54be58SFelix Manlunas static int liquidio_watchdog(void *param)
7509ff1a9baSRaghu Vatsavayi {
7519ff1a9baSRaghu Vatsavayi 	bool err_msg_was_printed[LIO_MAX_CORES];
752bb54be58SFelix Manlunas 	u16 mask_of_crashed_or_stuck_cores = 0;
753bb54be58SFelix Manlunas 	bool all_vf_links_are_disabled = false;
754bb54be58SFelix Manlunas 	struct octeon_device *oct = param;
7559ff1a9baSRaghu Vatsavayi 	struct octeon_device *other_oct;
756bb54be58SFelix Manlunas #ifdef CONFIG_MODULE_UNLOAD
757bb54be58SFelix Manlunas 	long refcount, vfs_referencing_pf;
758bb54be58SFelix Manlunas 	u64 vfs_mask1, vfs_mask2;
759bb54be58SFelix Manlunas #endif
760bb54be58SFelix Manlunas 	int core;
761bb54be58SFelix Manlunas 
7629ff1a9baSRaghu Vatsavayi 	memset(err_msg_was_printed, 0, sizeof(err_msg_was_printed));
763bb54be58SFelix Manlunas 
7649ff1a9baSRaghu Vatsavayi 	while (!kthread_should_stop()) {
7659ff1a9baSRaghu Vatsavayi 		/* sleep for a couple of seconds so that we don't hog the CPU */
766bb54be58SFelix Manlunas 		set_current_state(TASK_INTERRUPTIBLE);
767bb54be58SFelix Manlunas 		schedule_timeout(msecs_to_jiffies(2000));
768bb54be58SFelix Manlunas 
769bb54be58SFelix Manlunas 		mask_of_crashed_or_stuck_cores =
770bb54be58SFelix Manlunas 		    (u16)octeon_read_csr64(oct, CN23XX_SLI_SCRATCH2);
7719ff1a9baSRaghu Vatsavayi 
7729ff1a9baSRaghu Vatsavayi 		if (!mask_of_crashed_or_stuck_cores)
773bb54be58SFelix Manlunas 			continue;
774bb54be58SFelix Manlunas 
7759ff1a9baSRaghu Vatsavayi 		WRITE_ONCE(oct->cores_crashed, true);
776bb54be58SFelix Manlunas 		other_oct = get_other_octeon_device(oct);
777bb54be58SFelix Manlunas 		if (other_oct)
778bb54be58SFelix Manlunas 			WRITE_ONCE(other_oct->cores_crashed, true);
779bb54be58SFelix Manlunas 
7809ff1a9baSRaghu Vatsavayi 		for (core = 0; core < LIO_MAX_CORES; core++) {
781bb54be58SFelix Manlunas 			bool core_crashed_or_got_stuck;
782bb54be58SFelix Manlunas 
7839ff1a9baSRaghu Vatsavayi 			core_crashed_or_got_stuck =
784bb54be58SFelix Manlunas 						(mask_of_crashed_or_stuck_cores
785bb54be58SFelix Manlunas 						 >> core) & 1;
786bb54be58SFelix Manlunas 
787bb54be58SFelix Manlunas 			if (core_crashed_or_got_stuck &&
788bb54be58SFelix Manlunas 			    !err_msg_was_printed[core]) {
789bb54be58SFelix Manlunas 				dev_err(&oct->pci_dev->dev,
7909ff1a9baSRaghu Vatsavayi 					"ERROR: Octeon core %d crashed or got stuck!  See oct-fwdump for details.\n",
791bb54be58SFelix Manlunas 					core);
792bb54be58SFelix Manlunas 				err_msg_was_printed[core] = true;
793bb54be58SFelix Manlunas 			}
7949ff1a9baSRaghu Vatsavayi 		}
7959ff1a9baSRaghu Vatsavayi 
7969ff1a9baSRaghu Vatsavayi 		if (all_vf_links_are_disabled)
797bb54be58SFelix Manlunas 			continue;
798bb54be58SFelix Manlunas 
799bb54be58SFelix Manlunas 		disable_all_vf_links(oct);
800bb54be58SFelix Manlunas 		disable_all_vf_links(other_oct);
801bb54be58SFelix Manlunas 		all_vf_links_are_disabled = true;
802bb54be58SFelix Manlunas 
803bb54be58SFelix Manlunas #ifdef CONFIG_MODULE_UNLOAD
8049ff1a9baSRaghu Vatsavayi 		vfs_mask1 = READ_ONCE(oct->sriov_info.vf_drv_loaded_mask);
805bb54be58SFelix Manlunas 		vfs_mask2 = READ_ONCE(other_oct->sriov_info.vf_drv_loaded_mask);
806bb54be58SFelix Manlunas 
807bb54be58SFelix Manlunas 		vfs_referencing_pf  = hweight64(vfs_mask1);
808bb54be58SFelix Manlunas 		vfs_referencing_pf += hweight64(vfs_mask2);
809bb54be58SFelix Manlunas 
8109ff1a9baSRaghu Vatsavayi 		refcount = module_refcount(THIS_MODULE);
8119ff1a9baSRaghu Vatsavayi 		if (refcount >= vfs_referencing_pf) {
812bb54be58SFelix Manlunas 			while (vfs_referencing_pf) {
813bb54be58SFelix Manlunas 				module_put(THIS_MODULE);
8149ff1a9baSRaghu Vatsavayi 				vfs_referencing_pf--;
815bb54be58SFelix Manlunas 			}
8169ff1a9baSRaghu Vatsavayi 		}
8179ff1a9baSRaghu Vatsavayi #endif
8189ff1a9baSRaghu Vatsavayi 	}
8199ff1a9baSRaghu Vatsavayi 
8209ff1a9baSRaghu Vatsavayi 	return 0;
8219ff1a9baSRaghu Vatsavayi }
8229ff1a9baSRaghu Vatsavayi 
8239ff1a9baSRaghu Vatsavayi /**
824f21fb3edSRaghu Vatsavayi  * liquidio_probe - PCI probe handler
825d0ea5cbdSJesse Brandeburg  * @pdev: PCI device structure
826d0ea5cbdSJesse Brandeburg  * @ent: unused
827d0ea5cbdSJesse Brandeburg  */
828f21fb3edSRaghu Vatsavayi static int
liquidio_probe(struct pci_dev * pdev,const struct pci_device_id __maybe_unused * ent)829a7d5a3dcSRaghu Vatsavayi liquidio_probe(struct pci_dev *pdev, const struct pci_device_id __maybe_unused *ent)
830d0ea5cbdSJesse Brandeburg {
831f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct_dev = NULL;
832f21fb3edSRaghu Vatsavayi 	struct handshake *hs;
833f21fb3edSRaghu Vatsavayi 
834f21fb3edSRaghu Vatsavayi 	oct_dev = octeon_allocate_device(pdev->device,
835f21fb3edSRaghu Vatsavayi 					 sizeof(struct octeon_device_priv));
836f21fb3edSRaghu Vatsavayi 	if (!oct_dev) {
837f21fb3edSRaghu Vatsavayi 		dev_err(&pdev->dev, "Unable to allocate device\n");
838f21fb3edSRaghu Vatsavayi 		return -ENOMEM;
839f21fb3edSRaghu Vatsavayi 	}
840f21fb3edSRaghu Vatsavayi 
841f21fb3edSRaghu Vatsavayi 	if (pdev->device == OCTEON_CN23XX_PF_VID)
8425b07aee1SRaghu Vatsavayi 		oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED;
8435b07aee1SRaghu Vatsavayi 
8445b07aee1SRaghu Vatsavayi 	/* Enable PTP for 6XXX Device */
845aa69ff9eSIntiyaz Basha 	if (((pdev->device == OCTEON_CN66XX) ||
846aa69ff9eSIntiyaz Basha 	     (pdev->device == OCTEON_CN68XX)))
847aa69ff9eSIntiyaz Basha 		oct_dev->ptp_enable = true;
848aa69ff9eSIntiyaz Basha 	else
849aa69ff9eSIntiyaz Basha 		oct_dev->ptp_enable = false;
850aa69ff9eSIntiyaz Basha 
851aa69ff9eSIntiyaz Basha 	dev_info(&pdev->dev, "Initializing device %x:%x.\n",
852f21fb3edSRaghu Vatsavayi 		 (u32)pdev->vendor, (u32)pdev->device);
853f21fb3edSRaghu Vatsavayi 
854f21fb3edSRaghu Vatsavayi 	/* Assign octeon_device for this device to the private data area. */
855f21fb3edSRaghu Vatsavayi 	pci_set_drvdata(pdev, oct_dev);
856f21fb3edSRaghu Vatsavayi 
857f21fb3edSRaghu Vatsavayi 	/* set linux specific device pointer */
858f21fb3edSRaghu Vatsavayi 	oct_dev->pci_dev = (void *)pdev;
859f21fb3edSRaghu Vatsavayi 
860f21fb3edSRaghu Vatsavayi 	oct_dev->subsystem_id = pdev->subsystem_vendor |
86118b338f5SWeilin Chang 		(pdev->subsystem_device << 16);
86218b338f5SWeilin Chang 
86318b338f5SWeilin Chang 	hs = &handshake[oct_dev->octeon_id];
864f21fb3edSRaghu Vatsavayi 	init_completion(&hs->init);
865f21fb3edSRaghu Vatsavayi 	init_completion(&hs->started);
866f21fb3edSRaghu Vatsavayi 	hs->pci_dev = pdev;
867f21fb3edSRaghu Vatsavayi 
868f21fb3edSRaghu Vatsavayi 	if (oct_dev->octeon_id == 0)
869f21fb3edSRaghu Vatsavayi 		/* first LiquidIO NIC is detected */
870f21fb3edSRaghu Vatsavayi 		complete(&first_stage);
871f21fb3edSRaghu Vatsavayi 
872f21fb3edSRaghu Vatsavayi 	if (octeon_device_init(oct_dev)) {
873f21fb3edSRaghu Vatsavayi 		complete(&hs->init);
874515e752dSRaghu Vatsavayi 		liquidio_remove(pdev);
875f21fb3edSRaghu Vatsavayi 		return -ENOMEM;
876f21fb3edSRaghu Vatsavayi 	}
877f21fb3edSRaghu Vatsavayi 
878f21fb3edSRaghu Vatsavayi 	if (OCTEON_CN23XX_PF(oct_dev)) {
8799ff1a9baSRaghu Vatsavayi 		u8 bus, device, function;
8809ff1a9baSRaghu Vatsavayi 
8819ff1a9baSRaghu Vatsavayi 		if (atomic_read(oct_dev->adapter_refcount) == 1) {
882392209faSFelix Manlunas 			/* Each NIC gets one watchdog kernel thread.  The first
883392209faSFelix Manlunas 			 * PF (of each NIC) that gets pci_driver->probe()'d
884392209faSFelix Manlunas 			 * creates that thread.
885392209faSFelix Manlunas 			 */
8869ff1a9baSRaghu Vatsavayi 			bus = pdev->bus->number;
8879ff1a9baSRaghu Vatsavayi 			device = PCI_SLOT(pdev->devfn);
8889ff1a9baSRaghu Vatsavayi 			function = PCI_FUNC(pdev->devfn);
8899ff1a9baSRaghu Vatsavayi 			oct_dev->watchdog_task = kthread_run(liquidio_watchdog,
89047b06824SCai Huoqing 							     oct_dev,
89147b06824SCai Huoqing 							     "liowd/%02hhx:%02hhx.%hhx",
89247b06824SCai Huoqing 							     bus, device, function);
89347b06824SCai Huoqing 			if (IS_ERR(oct_dev->watchdog_task)) {
89447b06824SCai Huoqing 				oct_dev->watchdog_task = NULL;
895515e752dSRaghu Vatsavayi 				dev_err(&oct_dev->pci_dev->dev,
896515e752dSRaghu Vatsavayi 					"failed to create kernel_thread\n");
897515e752dSRaghu Vatsavayi 				liquidio_remove(pdev);
898515e752dSRaghu Vatsavayi 				return -1;
899515e752dSRaghu Vatsavayi 			}
900515e752dSRaghu Vatsavayi 		}
9019ff1a9baSRaghu Vatsavayi 	}
9029ff1a9baSRaghu Vatsavayi 
9039ff1a9baSRaghu Vatsavayi 	oct_dev->rx_pause = 1;
9041f164717SRaghu Vatsavayi 	oct_dev->tx_pause = 1;
9051f164717SRaghu Vatsavayi 
9061f164717SRaghu Vatsavayi 	dev_dbg(&oct_dev->pci_dev->dev, "Device is ready\n");
907f21fb3edSRaghu Vatsavayi 
908f21fb3edSRaghu Vatsavayi 	return 0;
909f21fb3edSRaghu Vatsavayi }
910f21fb3edSRaghu Vatsavayi 
fw_type_is_auto(void)911f21fb3edSRaghu Vatsavayi static bool fw_type_is_auto(void)
912088b8749SRick Farrington {
9137cc61db9SFelix Manlunas 	return strncmp(fw_type, LIO_FW_NAME_TYPE_AUTO,
914088b8749SRick Farrington 		       sizeof(LIO_FW_NAME_TYPE_AUTO)) == 0;
915088b8749SRick Farrington }
9167cc61db9SFelix Manlunas 
9177cc61db9SFelix Manlunas /**
918f21fb3edSRaghu Vatsavayi  * octeon_pci_flr - PCI FLR for each Octeon device.
919d0ea5cbdSJesse Brandeburg  * @oct: octeon device
920d0ea5cbdSJesse Brandeburg  */
octeon_pci_flr(struct octeon_device * oct)92170535350SRick Farrington static void octeon_pci_flr(struct octeon_device *oct)
92270535350SRick Farrington {
92370535350SRick Farrington 	int rc;
92470535350SRick Farrington 
92570535350SRick Farrington 	pci_save_state(oct->pci_dev);
92670535350SRick Farrington 
92770535350SRick Farrington 	pci_cfg_access_lock(oct->pci_dev);
92870535350SRick Farrington 
92970535350SRick Farrington 	/* Quiesce the device completely */
93070535350SRick Farrington 	pci_write_config_word(oct->pci_dev, PCI_COMMAND,
93170535350SRick Farrington 			      PCI_COMMAND_INTX_DISABLE);
93270535350SRick Farrington 
93370535350SRick Farrington 	rc = __pci_reset_function_locked(oct->pci_dev);
93470535350SRick Farrington 
93570535350SRick Farrington 	if (rc != 0)
93670535350SRick Farrington 		dev_err(&oct->pci_dev->dev, "Error %d resetting PCI function %d\n",
93770535350SRick Farrington 			rc, oct->pf_num);
93870535350SRick Farrington 
93970535350SRick Farrington 	pci_cfg_access_unlock(oct->pci_dev);
94070535350SRick Farrington 
94170535350SRick Farrington 	pci_restore_state(oct->pci_dev);
94270535350SRick Farrington }
94370535350SRick Farrington 
94470535350SRick Farrington /**
94570535350SRick Farrington  * octeon_destroy_resources - Destroy resources associated with octeon device
946d0ea5cbdSJesse Brandeburg  * @oct: octeon device
947d0ea5cbdSJesse Brandeburg  */
octeon_destroy_resources(struct octeon_device * oct)948f21fb3edSRaghu Vatsavayi static void octeon_destroy_resources(struct octeon_device *oct)
949f21fb3edSRaghu Vatsavayi {
950f21fb3edSRaghu Vatsavayi 	int i, refcount;
951e1e3ce62SRick Farrington 	struct msix_entry *msix_entries;
9525b07aee1SRaghu Vatsavayi 	struct octeon_device_priv *oct_priv = oct->priv;
953f21fb3edSRaghu Vatsavayi 
954f21fb3edSRaghu Vatsavayi 	struct handshake *hs;
955f21fb3edSRaghu Vatsavayi 
956f21fb3edSRaghu Vatsavayi 	switch (atomic_read(&oct->status)) {
957f21fb3edSRaghu Vatsavayi 	case OCT_DEV_RUNNING:
958f21fb3edSRaghu Vatsavayi 	case OCT_DEV_CORE_OK:
959f21fb3edSRaghu Vatsavayi 
960f21fb3edSRaghu Vatsavayi 		/* No more instructions will be forwarded. */
961f21fb3edSRaghu Vatsavayi 		atomic_set(&oct->status, OCT_DEV_IN_RESET);
962f21fb3edSRaghu Vatsavayi 
963f21fb3edSRaghu Vatsavayi 		oct->app_mode = CVM_DRV_INVALID_APP;
964f21fb3edSRaghu Vatsavayi 		dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
965f21fb3edSRaghu Vatsavayi 			lio_get_state_string(&oct->status));
966f21fb3edSRaghu Vatsavayi 
967f21fb3edSRaghu Vatsavayi 		schedule_timeout_uninterruptible(HZ / 10);
968f21fb3edSRaghu Vatsavayi 
969f21fb3edSRaghu Vatsavayi 		fallthrough;
970f21fb3edSRaghu Vatsavayi 	case OCT_DEV_HOST_OK:
971df561f66SGustavo A. R. Silva 
972f21fb3edSRaghu Vatsavayi 	case OCT_DEV_CONSOLE_INIT_DONE:
973f21fb3edSRaghu Vatsavayi 		/* Remove any consoles */
974f21fb3edSRaghu Vatsavayi 		octeon_remove_consoles(oct);
975f21fb3edSRaghu Vatsavayi 
976f21fb3edSRaghu Vatsavayi 		fallthrough;
977f21fb3edSRaghu Vatsavayi 	case OCT_DEV_IO_QUEUES_DONE:
978df561f66SGustavo A. R. Silva 		if (lio_wait_for_instr_fetch(oct))
979f21fb3edSRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");
980f21fb3edSRaghu Vatsavayi 
981f21fb3edSRaghu Vatsavayi 		if (wait_for_pending_requests(oct))
982f21fb3edSRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev, "There were pending requests\n");
983c9aec052SFelix Manlunas 
984c9aec052SFelix Manlunas 		/* Disable the input and output queues now. No more packets will
985c9aec052SFelix Manlunas 		 * arrive from Octeon, but we should wait for all packet
986f21fb3edSRaghu Vatsavayi 		 * processing to finish.
987f21fb3edSRaghu Vatsavayi 		 */
988f21fb3edSRaghu Vatsavayi 		oct->fn_list.disable_io_queues(oct);
989f21fb3edSRaghu Vatsavayi 
990f21fb3edSRaghu Vatsavayi 		if (lio_wait_for_oq_pkts(oct))
991f21fb3edSRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");
992f21fb3edSRaghu Vatsavayi 
993f21fb3edSRaghu Vatsavayi 		/* Force all requests waiting to be fetched by OCTEON to
994f21fb3edSRaghu Vatsavayi 		 * complete.
995c9aec052SFelix Manlunas 		 */
996c9aec052SFelix Manlunas 		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
997c9aec052SFelix Manlunas 			struct octeon_instr_queue *iq;
998c9aec052SFelix Manlunas 
999c9aec052SFelix Manlunas 			if (!(oct->io_qmask.iq & BIT_ULL(i)))
1000c9aec052SFelix Manlunas 				continue;
1001c9aec052SFelix Manlunas 			iq = oct->instr_queue[i];
1002c9aec052SFelix Manlunas 
1003c9aec052SFelix Manlunas 			if (atomic_read(&iq->instr_pending)) {
1004c9aec052SFelix Manlunas 				spin_lock_bh(&iq->lock);
1005c9aec052SFelix Manlunas 				iq->fill_cnt = 0;
1006c9aec052SFelix Manlunas 				iq->octeon_read_index = iq->host_write_index;
1007c9aec052SFelix Manlunas 				iq->stats.instr_processed +=
1008c9aec052SFelix Manlunas 					atomic_read(&iq->instr_pending);
1009c9aec052SFelix Manlunas 				lio_process_iq_request_list(oct, iq, 0);
1010c9aec052SFelix Manlunas 				spin_unlock_bh(&iq->lock);
1011c9aec052SFelix Manlunas 			}
1012c9aec052SFelix Manlunas 		}
1013c9aec052SFelix Manlunas 
1014c9aec052SFelix Manlunas 		lio_process_ordered_list(oct, 1);
1015c9aec052SFelix Manlunas 		octeon_free_sc_done_list(oct);
1016c9aec052SFelix Manlunas 		octeon_free_sc_zombie_list(oct);
1017c9aec052SFelix Manlunas 
1018c9aec052SFelix Manlunas 		fallthrough;
1019c9aec052SFelix Manlunas 	case OCT_DEV_INTR_SET_DONE:
1020df561f66SGustavo A. R. Silva 		/* Disable interrupts  */
1021515e752dSRaghu Vatsavayi 		oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
1022f21fb3edSRaghu Vatsavayi 
10235b07aee1SRaghu Vatsavayi 		if (oct->msix_on) {
1024f21fb3edSRaghu Vatsavayi 			msix_entries = (struct msix_entry *)oct->msix_entries;
10255b07aee1SRaghu Vatsavayi 			for (i = 0; i < oct->num_msix_irqs - 1; i++) {
10265b07aee1SRaghu Vatsavayi 				if (oct->ioq_vector[i].vector) {
10275b07aee1SRaghu Vatsavayi 					/* clear the affinity_cpumask */
1028a82457f1SIntiyaz Basha 					irq_set_affinity_hint(
10295b07aee1SRaghu Vatsavayi 							msix_entries[i].vector,
1030a82457f1SIntiyaz Basha 							NULL);
1031a82457f1SIntiyaz Basha 					free_irq(msix_entries[i].vector,
10325b07aee1SRaghu Vatsavayi 						 &oct->ioq_vector[i]);
10335b07aee1SRaghu Vatsavayi 					oct->ioq_vector[i].vector = 0;
10345b07aee1SRaghu Vatsavayi 				}
1035a82457f1SIntiyaz Basha 			}
1036a82457f1SIntiyaz Basha 			/* non-iov vector's argument is oct struct */
10375b07aee1SRaghu Vatsavayi 			free_irq(msix_entries[i].vector, oct);
10385b07aee1SRaghu Vatsavayi 
10395b07aee1SRaghu Vatsavayi 			pci_disable_msix(oct->pci_dev);
10405b07aee1SRaghu Vatsavayi 			kfree(oct->msix_entries);
10415b07aee1SRaghu Vatsavayi 			oct->msix_entries = NULL;
10425b07aee1SRaghu Vatsavayi 		} else {
10435b07aee1SRaghu Vatsavayi 			/* Release the interrupt line */
10445b07aee1SRaghu Vatsavayi 			free_irq(oct->pci_dev->irq, oct);
1045f21fb3edSRaghu Vatsavayi 
1046f21fb3edSRaghu Vatsavayi 			if (oct->flags & LIO_FLAG_MSI_ENABLED)
1047f21fb3edSRaghu Vatsavayi 				pci_disable_msi(oct->pci_dev);
1048f21fb3edSRaghu Vatsavayi 		}
1049f21fb3edSRaghu Vatsavayi 
10505b07aee1SRaghu Vatsavayi 		kfree(oct->irq_name_storage);
1051f21fb3edSRaghu Vatsavayi 		oct->irq_name_storage = NULL;
10520c88a761SRick Farrington 
10530c88a761SRick Farrington 		fallthrough;
10540c88a761SRick Farrington 	case OCT_DEV_MSIX_ALLOC_VECTOR_DONE:
1055df561f66SGustavo A. R. Silva 		if (OCTEON_CN23XX_PF(oct))
1056515e752dSRaghu Vatsavayi 			octeon_free_ioq_vector(oct);
10575b07aee1SRaghu Vatsavayi 
10585b07aee1SRaghu Vatsavayi 		fallthrough;
10595d65556bSRaghu Vatsavayi 	case OCT_DEV_MBOX_SETUP_DONE:
1060df561f66SGustavo A. R. Silva 		if (OCTEON_CN23XX_PF(oct))
10615d65556bSRaghu Vatsavayi 			oct->fn_list.free_mbox(oct);
10625d65556bSRaghu Vatsavayi 
10635d65556bSRaghu Vatsavayi 		fallthrough;
10645d65556bSRaghu Vatsavayi 	case OCT_DEV_IN_RESET:
1065df561f66SGustavo A. R. Silva 	case OCT_DEV_DROQ_INIT_DONE:
1066f21fb3edSRaghu Vatsavayi 		/* Wait for any pending operations */
1067f21fb3edSRaghu Vatsavayi 		mdelay(100);
1068763185a3SRaghu Vatsavayi 		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
1069f21fb3edSRaghu Vatsavayi 			if (!(oct->io_qmask.oq & BIT_ULL(i)))
107063da8404SRaghu Vatsavayi 				continue;
10715b07aee1SRaghu Vatsavayi 			octeon_delete_droq(oct, i);
1072f21fb3edSRaghu Vatsavayi 		}
1073f21fb3edSRaghu Vatsavayi 
1074f21fb3edSRaghu Vatsavayi 		/* Force any pending handshakes to complete */
1075f21fb3edSRaghu Vatsavayi 		for (i = 0; i < MAX_OCTEON_DEVICES; i++) {
1076f21fb3edSRaghu Vatsavayi 			hs = &handshake[i];
1077f21fb3edSRaghu Vatsavayi 
1078f21fb3edSRaghu Vatsavayi 			if (hs->pci_dev) {
1079f21fb3edSRaghu Vatsavayi 				handshake[oct->octeon_id].init_ok = 0;
1080f21fb3edSRaghu Vatsavayi 				complete(&handshake[oct->octeon_id].init);
1081f21fb3edSRaghu Vatsavayi 				handshake[oct->octeon_id].started_ok = 0;
1082f21fb3edSRaghu Vatsavayi 				complete(&handshake[oct->octeon_id].started);
1083f21fb3edSRaghu Vatsavayi 			}
1084f21fb3edSRaghu Vatsavayi 		}
1085f21fb3edSRaghu Vatsavayi 
1086f21fb3edSRaghu Vatsavayi 		fallthrough;
1087f21fb3edSRaghu Vatsavayi 	case OCT_DEV_RESP_LIST_INIT_DONE:
1088df561f66SGustavo A. R. Silva 		octeon_delete_response_list(oct);
1089f21fb3edSRaghu Vatsavayi 
1090f21fb3edSRaghu Vatsavayi 		fallthrough;
1091f21fb3edSRaghu Vatsavayi 	case OCT_DEV_INSTR_QUEUE_INIT_DONE:
1092df561f66SGustavo A. R. Silva 		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
1093f21fb3edSRaghu Vatsavayi 			if (!(oct->io_qmask.iq & BIT_ULL(i)))
109463da8404SRaghu Vatsavayi 				continue;
10955b823514SRaghu Vatsavayi 			octeon_delete_instr_queue(oct, i);
1096f21fb3edSRaghu Vatsavayi 		}
1097f21fb3edSRaghu Vatsavayi #ifdef CONFIG_PCI_IOV
1098f21fb3edSRaghu Vatsavayi 		if (oct->sriov_info.sriov_enabled)
1099ca6139ffSRaghu Vatsavayi 			pci_disable_sriov(oct->pci_dev);
1100ca6139ffSRaghu Vatsavayi #endif
1101ca6139ffSRaghu Vatsavayi 		fallthrough;
1102ca6139ffSRaghu Vatsavayi 	case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
1103df561f66SGustavo A. R. Silva 		octeon_free_sc_buffer_pool(oct);
11045b823514SRaghu Vatsavayi 
11055b823514SRaghu Vatsavayi 		fallthrough;
1106f21fb3edSRaghu Vatsavayi 	case OCT_DEV_DISPATCH_INIT_DONE:
1107df561f66SGustavo A. R. Silva 		octeon_delete_dispatch_list(oct);
1108f21fb3edSRaghu Vatsavayi 		cancel_delayed_work_sync(&oct->nic_poll_work.work);
1109f21fb3edSRaghu Vatsavayi 
1110f21fb3edSRaghu Vatsavayi 		fallthrough;
1111f21fb3edSRaghu Vatsavayi 	case OCT_DEV_PCI_MAP_DONE:
1112df561f66SGustavo A. R. Silva 		refcount = octeon_deregister_device(oct);
1113f21fb3edSRaghu Vatsavayi 
1114e1e3ce62SRick Farrington 		/* Soft reset the octeon device before exiting.
1115e1e3ce62SRick Farrington 		 * However, if fw was loaded from card (i.e. autoboot),
1116e1e3ce62SRick Farrington 		 * perform an FLR instead.
111770535350SRick Farrington 		 * Implementation note: only soft-reset the device
111870535350SRick Farrington 		 * if it is a CN6XXX OR the LAST CN23XX device.
111970535350SRick Farrington 		 */
112070535350SRick Farrington 		if (atomic_read(oct->adapter_fw_state) == FW_IS_PRELOADED)
1121e1e3ce62SRick Farrington 			octeon_pci_flr(oct);
1122088b8749SRick Farrington 		else if (OCTEON_CN6XXX(oct) || !refcount)
112370535350SRick Farrington 			oct->fn_list.soft_reset(oct);
112470535350SRick Farrington 
112560b48c5aSRaghu Vatsavayi 		octeon_unmap_pci_barx(oct, 0);
112660b48c5aSRaghu Vatsavayi 		octeon_unmap_pci_barx(oct, 1);
1127f21fb3edSRaghu Vatsavayi 
1128f21fb3edSRaghu Vatsavayi 		fallthrough;
1129f21fb3edSRaghu Vatsavayi 	case OCT_DEV_PCI_ENABLE_DONE:
1130df561f66SGustavo A. R. Silva 		/* Disable the device, releasing the PCI INT */
1131515e752dSRaghu Vatsavayi 		pci_disable_device(oct->pci_dev);
113260b48c5aSRaghu Vatsavayi 
113360b48c5aSRaghu Vatsavayi 		fallthrough;
113460b48c5aSRaghu Vatsavayi 	case OCT_DEV_BEGIN_STATE:
1135df561f66SGustavo A. R. Silva 		/* Nothing to be done here either */
1136515e752dSRaghu Vatsavayi 		break;
1137f21fb3edSRaghu Vatsavayi 	}                       /* end switch (oct->status) */
1138f21fb3edSRaghu Vatsavayi 
1139f21fb3edSRaghu Vatsavayi 	tasklet_kill(&oct_priv->droq_tasklet);
1140f21fb3edSRaghu Vatsavayi }
1141f21fb3edSRaghu Vatsavayi 
1142f21fb3edSRaghu Vatsavayi /**
1143f21fb3edSRaghu Vatsavayi  * send_rx_ctrl_cmd - Send Rx control command
1144f21fb3edSRaghu Vatsavayi  * @lio: per-network private data
1145d0ea5cbdSJesse Brandeburg  * @start_stop: whether to start or stop
1146d0ea5cbdSJesse Brandeburg  */
send_rx_ctrl_cmd(struct lio * lio,int start_stop)1147d0ea5cbdSJesse Brandeburg static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
1148f21fb3edSRaghu Vatsavayi {
1149dbc97bfdSTom Seewald 	struct octeon_soft_command *sc;
1150f21fb3edSRaghu Vatsavayi 	union octnet_cmd *ncmd;
1151afdf841fSRaghu Vatsavayi 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
1152afdf841fSRaghu Vatsavayi 	int retval;
1153afdf841fSRaghu Vatsavayi 
1154afdf841fSRaghu Vatsavayi 	if (oct->props[lio->ifidx].rx_on == start_stop)
1155f21fb3edSRaghu Vatsavayi 		return 0;
1156afdf841fSRaghu Vatsavayi 
1157dbc97bfdSTom Seewald 	sc = (struct octeon_soft_command *)
1158f21fb3edSRaghu Vatsavayi 		octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
1159afdf841fSRaghu Vatsavayi 					  16, 0);
1160afdf841fSRaghu Vatsavayi 	if (!sc) {
116164fecd3eSFelix Manlunas 		netif_info(lio, rx_err, lio->netdev,
1162dbc97bfdSTom Seewald 			   "Failed to allocate octeon_soft_command struct\n");
1163dbc97bfdSTom Seewald 		return -ENOMEM;
1164dbc97bfdSTom Seewald 	}
1165dbc97bfdSTom Seewald 
1166dbc97bfdSTom Seewald 	ncmd = (union octnet_cmd *)sc->virtdptr;
1167f21fb3edSRaghu Vatsavayi 
1168afdf841fSRaghu Vatsavayi 	ncmd->u64 = 0;
1169afdf841fSRaghu Vatsavayi 	ncmd->s.cmd = OCTNET_CMD_RX_CTL;
1170afdf841fSRaghu Vatsavayi 	ncmd->s.param1 = start_stop;
1171afdf841fSRaghu Vatsavayi 
1172afdf841fSRaghu Vatsavayi 	octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
1173afdf841fSRaghu Vatsavayi 
1174afdf841fSRaghu Vatsavayi 	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1175afdf841fSRaghu Vatsavayi 
1176afdf841fSRaghu Vatsavayi 	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
1177afdf841fSRaghu Vatsavayi 				    OPCODE_NIC_CMD, 0, 0, 0);
1178afdf841fSRaghu Vatsavayi 
1179afdf841fSRaghu Vatsavayi 	init_completion(&sc->complete);
1180afdf841fSRaghu Vatsavayi 	sc->sc_status = OCTEON_REQUEST_PENDING;
118164fecd3eSFelix Manlunas 
118264fecd3eSFelix Manlunas 	retval = octeon_send_soft_command(oct, sc);
1183afdf841fSRaghu Vatsavayi 	if (retval == IQ_SEND_FAILED) {
1184afdf841fSRaghu Vatsavayi 		netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n");
1185afdf841fSRaghu Vatsavayi 		octeon_free_soft_command(oct, sc);
1186f21fb3edSRaghu Vatsavayi 	} else {
118764fecd3eSFelix Manlunas 		/* Sleep on a wait queue till the cond flag indicates that the
1188afdf841fSRaghu Vatsavayi 		 * response arrived or timed-out.
1189afdf841fSRaghu Vatsavayi 		 */
1190afdf841fSRaghu Vatsavayi 		retval = wait_for_sc_completion_timeout(oct, sc, 0);
1191afdf841fSRaghu Vatsavayi 		if (retval)
119264fecd3eSFelix Manlunas 			return retval;
119364fecd3eSFelix Manlunas 
1194dbc97bfdSTom Seewald 		oct->props[lio->ifidx].rx_on = start_stop;
1195afdf841fSRaghu Vatsavayi 		WRITE_ONCE(sc->caller_is_done, true);
119664fecd3eSFelix Manlunas 	}
119764fecd3eSFelix Manlunas 
119864fecd3eSFelix Manlunas 	return retval;
1199dbc97bfdSTom Seewald }
1200dbc97bfdSTom Seewald 
1201f21fb3edSRaghu Vatsavayi /**
1202f21fb3edSRaghu Vatsavayi  * liquidio_destroy_nic_device - Destroy NIC device interface
1203f21fb3edSRaghu Vatsavayi  * @oct: octeon device
1204d0ea5cbdSJesse Brandeburg  * @ifidx: which interface to destroy
1205d0ea5cbdSJesse Brandeburg  *
1206d0ea5cbdSJesse Brandeburg  * Cleanup associated with each interface for an Octeon device  when NIC
1207f21fb3edSRaghu Vatsavayi  * module is being unloaded or if initialization fails during load.
1208f21fb3edSRaghu Vatsavayi  */
liquidio_destroy_nic_device(struct octeon_device * oct,int ifidx)1209f21fb3edSRaghu Vatsavayi static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
1210f21fb3edSRaghu Vatsavayi {
1211f21fb3edSRaghu Vatsavayi 	struct net_device *netdev = oct->props[ifidx].netdev;
1212f21fb3edSRaghu Vatsavayi 	struct octeon_device_priv *oct_priv = oct->priv;
1213f21fb3edSRaghu Vatsavayi 	struct napi_struct *napi, *n;
1214fe2d22b1SIntiyaz Basha 	struct lio *lio;
1215fe2d22b1SIntiyaz Basha 
12169a96bde4SRaghu Vatsavayi 	if (!netdev) {
1217fe2d22b1SIntiyaz Basha 		dev_err(&oct->pci_dev->dev, "%s No netdevice ptr for index %d\n",
1218f21fb3edSRaghu Vatsavayi 			__func__, ifidx);
1219f21fb3edSRaghu Vatsavayi 		return;
1220f21fb3edSRaghu Vatsavayi 	}
1221f21fb3edSRaghu Vatsavayi 
1222f21fb3edSRaghu Vatsavayi 	lio = GET_LIO(netdev);
1223f21fb3edSRaghu Vatsavayi 
1224f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct->pci_dev->dev, "NIC device cleanup\n");
1225f21fb3edSRaghu Vatsavayi 
1226f21fb3edSRaghu Vatsavayi 	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING)
1227f21fb3edSRaghu Vatsavayi 		liquidio_stop(netdev);
1228f21fb3edSRaghu Vatsavayi 
1229f21fb3edSRaghu Vatsavayi 	if (oct->props[lio->ifidx].napi_enabled == 1) {
1230afdf841fSRaghu Vatsavayi 		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
1231f21fb3edSRaghu Vatsavayi 			napi_disable(napi);
12329a96bde4SRaghu Vatsavayi 
12339a96bde4SRaghu Vatsavayi 		oct->props[lio->ifidx].napi_enabled = 0;
12349a96bde4SRaghu Vatsavayi 
12359a96bde4SRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(oct))
12369a96bde4SRaghu Vatsavayi 			oct->droq[0]->ops.poll_mode = 0;
12377b6b6c95SRaghu Vatsavayi 	}
12387b6b6c95SRaghu Vatsavayi 
12397b6b6c95SRaghu Vatsavayi 	/* Delete NAPI */
12409a96bde4SRaghu Vatsavayi 	list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
12419a96bde4SRaghu Vatsavayi 		netif_napi_del(napi);
124242013e90SIntiyaz Basha 
124342013e90SIntiyaz Basha 	tasklet_enable(&oct_priv->droq_tasklet);
124442013e90SIntiyaz Basha 
124542013e90SIntiyaz Basha 	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
1246fe2d22b1SIntiyaz Basha 		unregister_netdev(netdev);
1247fe2d22b1SIntiyaz Basha 
1248f21fb3edSRaghu Vatsavayi 	cleanup_sync_octeon_time_wq(netdev);
1249f21fb3edSRaghu Vatsavayi 	cleanup_link_status_change_wq(netdev);
1250f21fb3edSRaghu Vatsavayi 
1251907aaa6bSVeerasenareddy Burru 	cleanup_rx_oom_poll_fn(netdev);
12527b6b6c95SRaghu Vatsavayi 
12537b6b6c95SRaghu Vatsavayi 	lio_delete_glists(lio);
1254031d4f12SSatanand Burla 
1255031d4f12SSatanand Burla 	free_netdev(netdev);
1256fd311f1eSIntiyaz Basha 
1257f21fb3edSRaghu Vatsavayi 	oct->props[ifidx].gmxport = -1;
1258f21fb3edSRaghu Vatsavayi 
1259f21fb3edSRaghu Vatsavayi 	oct->props[ifidx].netdev = NULL;
12600cece6c5SRaghu Vatsavayi }
12610cece6c5SRaghu Vatsavayi 
1262f21fb3edSRaghu Vatsavayi /**
1263f21fb3edSRaghu Vatsavayi  * liquidio_stop_nic_module - Stop complete NIC functionality
1264f21fb3edSRaghu Vatsavayi  * @oct: octeon device
1265f21fb3edSRaghu Vatsavayi  */
liquidio_stop_nic_module(struct octeon_device * oct)1266d0ea5cbdSJesse Brandeburg static int liquidio_stop_nic_module(struct octeon_device *oct)
1267d0ea5cbdSJesse Brandeburg {
1268f21fb3edSRaghu Vatsavayi 	int i, j;
1269f21fb3edSRaghu Vatsavayi 	struct lio *lio;
1270f21fb3edSRaghu Vatsavayi 
1271f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct->pci_dev->dev, "Stopping network interfaces\n");
1272f21fb3edSRaghu Vatsavayi 	device_lock(&oct->pci_dev->dev);
1273f21fb3edSRaghu Vatsavayi 	if (oct->devlink) {
1274f21fb3edSRaghu Vatsavayi 		devlink_unregister(oct->devlink);
12758d44b5cfSLeon Romanovsky 		devlink_free(oct->devlink);
12768d44b5cfSLeon Romanovsky 		oct->devlink = NULL;
12778d44b5cfSLeon Romanovsky 	}
12788d44b5cfSLeon Romanovsky 	device_unlock(&oct->pci_dev->dev);
12798d44b5cfSLeon Romanovsky 
12808d44b5cfSLeon Romanovsky 	if (!oct->ifcount) {
12818d44b5cfSLeon Romanovsky 		dev_err(&oct->pci_dev->dev, "Init for Octeon was not completed\n");
12828d44b5cfSLeon Romanovsky 		return 1;
1283f21fb3edSRaghu Vatsavayi 	}
1284f21fb3edSRaghu Vatsavayi 
1285f21fb3edSRaghu Vatsavayi 	spin_lock_bh(&oct->cmd_resp_wqlock);
1286f21fb3edSRaghu Vatsavayi 	oct->cmd_resp_state = OCT_DRV_OFFLINE;
1287f21fb3edSRaghu Vatsavayi 	spin_unlock_bh(&oct->cmd_resp_wqlock);
128860441888SRaghu Vatsavayi 
128960441888SRaghu Vatsavayi 	lio_vf_rep_destroy(oct);
129060441888SRaghu Vatsavayi 
129160441888SRaghu Vatsavayi 	for (i = 0; i < oct->ifcount; i++) {
1292d4be8ebeSVijaya Mohan Guvva 		lio = GET_LIO(oct->props[i].netdev);
1293d4be8ebeSVijaya Mohan Guvva 		for (j = 0; j < oct->num_oqs; j++)
1294f21fb3edSRaghu Vatsavayi 			octeon_unregister_droq_ops(oct,
1295f21fb3edSRaghu Vatsavayi 						   lio->linfo.rxpciq[j].s.q_no);
1296a82457f1SIntiyaz Basha 	}
129726236fa9SRaghu Vatsavayi 
129826236fa9SRaghu Vatsavayi 	for (i = 0; i < oct->ifcount; i++)
1299f21fb3edSRaghu Vatsavayi 		liquidio_destroy_nic_device(oct, i);
1300f21fb3edSRaghu Vatsavayi 
1301f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct->pci_dev->dev, "Network interfaces stopped\n");
1302f21fb3edSRaghu Vatsavayi 	return 0;
1303f21fb3edSRaghu Vatsavayi }
1304f21fb3edSRaghu Vatsavayi 
1305f21fb3edSRaghu Vatsavayi /**
1306f21fb3edSRaghu Vatsavayi  * liquidio_remove - Cleans up resources at unload time
1307f21fb3edSRaghu Vatsavayi  * @pdev: PCI device structure
1308f21fb3edSRaghu Vatsavayi  */
liquidio_remove(struct pci_dev * pdev)1309d0ea5cbdSJesse Brandeburg static void liquidio_remove(struct pci_dev *pdev)
1310d0ea5cbdSJesse Brandeburg {
1311f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct_dev = pci_get_drvdata(pdev);
1312f21fb3edSRaghu Vatsavayi 
1313f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n");
1314f21fb3edSRaghu Vatsavayi 
1315f21fb3edSRaghu Vatsavayi 	if (oct_dev->watchdog_task)
1316f21fb3edSRaghu Vatsavayi 		kthread_stop(oct_dev->watchdog_task);
1317f21fb3edSRaghu Vatsavayi 
13189ff1a9baSRaghu Vatsavayi 	if (!oct_dev->octeon_id &&
13199ff1a9baSRaghu Vatsavayi 	    oct_dev->fw_info.app_cap_flags & LIQUIDIO_SWITCHDEV_CAP)
13209ff1a9baSRaghu Vatsavayi 		lio_vf_rep_modexit();
1321e20f4696SVijaya Mohan Guvva 
1322e20f4696SVijaya Mohan Guvva 	if (oct_dev->app_mode && (oct_dev->app_mode == CVM_DRV_NIC_APP))
1323e20f4696SVijaya Mohan Guvva 		liquidio_stop_nic_module(oct_dev);
1324e20f4696SVijaya Mohan Guvva 
1325f21fb3edSRaghu Vatsavayi 	/* Reset the octeon device and cleanup all memory allocated for
1326f21fb3edSRaghu Vatsavayi 	 * the octeon device by driver.
1327f21fb3edSRaghu Vatsavayi 	 */
1328f21fb3edSRaghu Vatsavayi 	octeon_destroy_resources(oct_dev);
1329f21fb3edSRaghu Vatsavayi 
1330f21fb3edSRaghu Vatsavayi 	dev_info(&oct_dev->pci_dev->dev, "Device removed\n");
1331f21fb3edSRaghu Vatsavayi 
1332f21fb3edSRaghu Vatsavayi 	/* This octeon device has been removed. Update the global
1333f21fb3edSRaghu Vatsavayi 	 * data structure to reflect this. Free the device structure.
1334f21fb3edSRaghu Vatsavayi 	 */
1335f21fb3edSRaghu Vatsavayi 	octeon_free_device_mem(oct_dev);
1336f21fb3edSRaghu Vatsavayi }
1337f21fb3edSRaghu Vatsavayi 
1338f21fb3edSRaghu Vatsavayi /**
1339f21fb3edSRaghu Vatsavayi  * octeon_chip_specific_setup - Identify the Octeon device and to map the BAR address space
1340f21fb3edSRaghu Vatsavayi  * @oct: octeon device
1341f21fb3edSRaghu Vatsavayi  */
octeon_chip_specific_setup(struct octeon_device * oct)1342d0ea5cbdSJesse Brandeburg static int octeon_chip_specific_setup(struct octeon_device *oct)
1343d0ea5cbdSJesse Brandeburg {
1344f21fb3edSRaghu Vatsavayi 	u32 dev_id, rev_id;
1345f21fb3edSRaghu Vatsavayi 	int ret = 1;
1346f21fb3edSRaghu Vatsavayi 
1347f21fb3edSRaghu Vatsavayi 	pci_read_config_dword(oct->pci_dev, 0, &dev_id);
1348f21fb3edSRaghu Vatsavayi 	pci_read_config_dword(oct->pci_dev, 8, &rev_id);
1349f21fb3edSRaghu Vatsavayi 	oct->rev_id = rev_id & 0xff;
1350f21fb3edSRaghu Vatsavayi 
1351f21fb3edSRaghu Vatsavayi 	switch (dev_id) {
1352f21fb3edSRaghu Vatsavayi 	case OCTEON_CN68XX_PCIID:
1353f21fb3edSRaghu Vatsavayi 		oct->chip_id = OCTEON_CN68XX;
1354f21fb3edSRaghu Vatsavayi 		ret = lio_setup_cn68xx_octeon_device(oct);
1355f21fb3edSRaghu Vatsavayi 		break;
1356f21fb3edSRaghu Vatsavayi 
1357f21fb3edSRaghu Vatsavayi 	case OCTEON_CN66XX_PCIID:
1358f21fb3edSRaghu Vatsavayi 		oct->chip_id = OCTEON_CN66XX;
1359f21fb3edSRaghu Vatsavayi 		ret = lio_setup_cn66xx_octeon_device(oct);
1360f21fb3edSRaghu Vatsavayi 		break;
1361f21fb3edSRaghu Vatsavayi 
1362f21fb3edSRaghu Vatsavayi 	case OCTEON_CN23XX_PCIID_PF:
1363f21fb3edSRaghu Vatsavayi 		oct->chip_id = OCTEON_CN23XX_PF_VID;
1364d3d7e6c6SRaghu Vatsavayi 		ret = setup_cn23xx_octeon_pf_device(oct);
136572c00912SRaghu Vatsavayi 		if (ret)
136672c00912SRaghu Vatsavayi 			break;
136772c00912SRaghu Vatsavayi #ifdef CONFIG_PCI_IOV
13680c45d7feSRick Farrington 		if (!ret)
13690c45d7feSRick Farrington 			pci_sriov_set_totalvfs(oct->pci_dev,
1370cf19a8c3SDerek Chickles 					       oct->sriov_info.max_vfs);
1371cf19a8c3SDerek Chickles #endif
1372cf19a8c3SDerek Chickles 		break;
1373cf19a8c3SDerek Chickles 
1374cf19a8c3SDerek Chickles 	default:
137572c00912SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Unknown device found (dev_id: %x)\n",
137672c00912SRaghu Vatsavayi 			dev_id);
1377f21fb3edSRaghu Vatsavayi 	}
1378f21fb3edSRaghu Vatsavayi 
1379f21fb3edSRaghu Vatsavayi 	return ret;
1380f21fb3edSRaghu Vatsavayi }
1381f21fb3edSRaghu Vatsavayi 
1382f21fb3edSRaghu Vatsavayi /**
1383f21fb3edSRaghu Vatsavayi  * octeon_pci_os_setup - PCI initialization for each Octeon device.
1384f21fb3edSRaghu Vatsavayi  * @oct: octeon device
1385f21fb3edSRaghu Vatsavayi  */
octeon_pci_os_setup(struct octeon_device * oct)1386d0ea5cbdSJesse Brandeburg static int octeon_pci_os_setup(struct octeon_device *oct)
1387d0ea5cbdSJesse Brandeburg {
1388f21fb3edSRaghu Vatsavayi 	/* setup PCI stuff first */
1389f21fb3edSRaghu Vatsavayi 	if (pci_enable_device(oct->pci_dev)) {
1390f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "pci_enable_device failed\n");
1391f21fb3edSRaghu Vatsavayi 		return 1;
1392f21fb3edSRaghu Vatsavayi 	}
1393f21fb3edSRaghu Vatsavayi 
1394f21fb3edSRaghu Vatsavayi 	if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) {
1395f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n");
1396f21fb3edSRaghu Vatsavayi 		pci_disable_device(oct->pci_dev);
1397f21fb3edSRaghu Vatsavayi 		return 1;
1398f21fb3edSRaghu Vatsavayi 	}
1399515e752dSRaghu Vatsavayi 
1400f21fb3edSRaghu Vatsavayi 	/* Enable PCI DMA Master. */
1401f21fb3edSRaghu Vatsavayi 	pci_set_master(oct->pci_dev);
1402f21fb3edSRaghu Vatsavayi 
1403f21fb3edSRaghu Vatsavayi 	return 0;
1404f21fb3edSRaghu Vatsavayi }
1405f21fb3edSRaghu Vatsavayi 
1406f21fb3edSRaghu Vatsavayi /**
1407f21fb3edSRaghu Vatsavayi  * free_netbuf - Unmap and free network buffer
1408f21fb3edSRaghu Vatsavayi  * @buf: buffer
1409f21fb3edSRaghu Vatsavayi  */
free_netbuf(void * buf)1410d0ea5cbdSJesse Brandeburg static void free_netbuf(void *buf)
1411d0ea5cbdSJesse Brandeburg {
1412f21fb3edSRaghu Vatsavayi 	struct sk_buff *skb;
1413f21fb3edSRaghu Vatsavayi 	struct octnet_buf_free_info *finfo;
1414f21fb3edSRaghu Vatsavayi 	struct lio *lio;
1415f21fb3edSRaghu Vatsavayi 
1416f21fb3edSRaghu Vatsavayi 	finfo = (struct octnet_buf_free_info *)buf;
1417f21fb3edSRaghu Vatsavayi 	skb = finfo->skb;
1418f21fb3edSRaghu Vatsavayi 	lio = finfo->lio;
1419f21fb3edSRaghu Vatsavayi 
1420f21fb3edSRaghu Vatsavayi 	dma_unmap_single(&lio->oct_dev->pci_dev->dev, finfo->dptr, skb->len,
1421f21fb3edSRaghu Vatsavayi 			 DMA_TO_DEVICE);
1422f21fb3edSRaghu Vatsavayi 
1423f21fb3edSRaghu Vatsavayi 	tx_buffer_free(skb);
1424f21fb3edSRaghu Vatsavayi }
1425f21fb3edSRaghu Vatsavayi 
1426cabeb13bSRaghu Vatsavayi /**
1427f21fb3edSRaghu Vatsavayi  * free_netsgbuf - Unmap and free gather buffer
1428f21fb3edSRaghu Vatsavayi  * @buf: buffer
1429f21fb3edSRaghu Vatsavayi  */
free_netsgbuf(void * buf)1430d0ea5cbdSJesse Brandeburg static void free_netsgbuf(void *buf)
1431d0ea5cbdSJesse Brandeburg {
1432f21fb3edSRaghu Vatsavayi 	struct octnet_buf_free_info *finfo;
1433f21fb3edSRaghu Vatsavayi 	struct sk_buff *skb;
1434f21fb3edSRaghu Vatsavayi 	struct lio *lio;
1435f21fb3edSRaghu Vatsavayi 	struct octnic_gather *g;
1436f21fb3edSRaghu Vatsavayi 	int i, frags, iq;
1437f21fb3edSRaghu Vatsavayi 
1438f21fb3edSRaghu Vatsavayi 	finfo = (struct octnet_buf_free_info *)buf;
1439fcd2b5e3SRaghu Vatsavayi 	skb = finfo->skb;
1440f21fb3edSRaghu Vatsavayi 	lio = finfo->lio;
1441f21fb3edSRaghu Vatsavayi 	g = finfo->g;
1442f21fb3edSRaghu Vatsavayi 	frags = skb_shinfo(skb)->nr_frags;
1443f21fb3edSRaghu Vatsavayi 
1444f21fb3edSRaghu Vatsavayi 	dma_unmap_single(&lio->oct_dev->pci_dev->dev,
1445f21fb3edSRaghu Vatsavayi 			 g->sg[0].ptr[0], (skb->len - skb->data_len),
1446f21fb3edSRaghu Vatsavayi 			 DMA_TO_DEVICE);
1447f21fb3edSRaghu Vatsavayi 
1448f21fb3edSRaghu Vatsavayi 	i = 1;
1449f21fb3edSRaghu Vatsavayi 	while (frags--) {
1450f21fb3edSRaghu Vatsavayi 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
1451f21fb3edSRaghu Vatsavayi 
1452f21fb3edSRaghu Vatsavayi 		dma_unmap_page(&lio->oct_dev->pci_dev->dev,
1453d7840976SMatthew Wilcox (Oracle) 			       g->sg[(i >> 2)].ptr[(i & 3)],
1454f21fb3edSRaghu Vatsavayi 			       skb_frag_size(frag), DMA_TO_DEVICE);
14551e0dd56eSChristophe JAILLET 		i++;
1456f21fb3edSRaghu Vatsavayi 	}
1457d7840976SMatthew Wilcox (Oracle) 
1458f21fb3edSRaghu Vatsavayi 	iq = skb_iq(lio->oct_dev, skb);
1459f21fb3edSRaghu Vatsavayi 	spin_lock(&lio->glist_lock[iq]);
1460f21fb3edSRaghu Vatsavayi 	list_add_tail(&g->list, &lio->glist[iq]);
1461c33c9973SIntiyaz Basha 	spin_unlock(&lio->glist_lock[iq]);
1462fcd2b5e3SRaghu Vatsavayi 
1463fcd2b5e3SRaghu Vatsavayi 	tx_buffer_free(skb);
1464fcd2b5e3SRaghu Vatsavayi }
1465f21fb3edSRaghu Vatsavayi 
1466cabeb13bSRaghu Vatsavayi /**
1467f21fb3edSRaghu Vatsavayi  * free_netsgbuf_with_resp - Unmap and free gather buffer with response
1468f21fb3edSRaghu Vatsavayi  * @buf: buffer
1469f21fb3edSRaghu Vatsavayi  */
free_netsgbuf_with_resp(void * buf)1470d0ea5cbdSJesse Brandeburg static void free_netsgbuf_with_resp(void *buf)
1471d0ea5cbdSJesse Brandeburg {
1472f21fb3edSRaghu Vatsavayi 	struct octeon_soft_command *sc;
1473f21fb3edSRaghu Vatsavayi 	struct octnet_buf_free_info *finfo;
1474f21fb3edSRaghu Vatsavayi 	struct sk_buff *skb;
1475f21fb3edSRaghu Vatsavayi 	struct lio *lio;
1476f21fb3edSRaghu Vatsavayi 	struct octnic_gather *g;
1477f21fb3edSRaghu Vatsavayi 	int i, frags, iq;
1478f21fb3edSRaghu Vatsavayi 
1479f21fb3edSRaghu Vatsavayi 	sc = (struct octeon_soft_command *)buf;
1480fcd2b5e3SRaghu Vatsavayi 	skb = (struct sk_buff *)sc->callback_arg;
1481f21fb3edSRaghu Vatsavayi 	finfo = (struct octnet_buf_free_info *)&skb->cb;
1482f21fb3edSRaghu Vatsavayi 
1483f21fb3edSRaghu Vatsavayi 	lio = finfo->lio;
1484f21fb3edSRaghu Vatsavayi 	g = finfo->g;
1485f21fb3edSRaghu Vatsavayi 	frags = skb_shinfo(skb)->nr_frags;
1486f21fb3edSRaghu Vatsavayi 
1487f21fb3edSRaghu Vatsavayi 	dma_unmap_single(&lio->oct_dev->pci_dev->dev,
1488f21fb3edSRaghu Vatsavayi 			 g->sg[0].ptr[0], (skb->len - skb->data_len),
1489f21fb3edSRaghu Vatsavayi 			 DMA_TO_DEVICE);
1490f21fb3edSRaghu Vatsavayi 
1491f21fb3edSRaghu Vatsavayi 	i = 1;
1492f21fb3edSRaghu Vatsavayi 	while (frags--) {
1493f21fb3edSRaghu Vatsavayi 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
1494f21fb3edSRaghu Vatsavayi 
1495f21fb3edSRaghu Vatsavayi 		dma_unmap_page(&lio->oct_dev->pci_dev->dev,
1496d7840976SMatthew Wilcox (Oracle) 			       g->sg[(i >> 2)].ptr[(i & 3)],
1497f21fb3edSRaghu Vatsavayi 			       skb_frag_size(frag), DMA_TO_DEVICE);
14981e0dd56eSChristophe JAILLET 		i++;
1499f21fb3edSRaghu Vatsavayi 	}
1500d7840976SMatthew Wilcox (Oracle) 
1501f21fb3edSRaghu Vatsavayi 	iq = skb_iq(lio->oct_dev, skb);
1502f21fb3edSRaghu Vatsavayi 
1503f21fb3edSRaghu Vatsavayi 	spin_lock(&lio->glist_lock[iq]);
1504c33c9973SIntiyaz Basha 	list_add_tail(&g->list, &lio->glist[iq]);
1505fcd2b5e3SRaghu Vatsavayi 	spin_unlock(&lio->glist_lock[iq]);
1506fcd2b5e3SRaghu Vatsavayi 
1507fcd2b5e3SRaghu Vatsavayi 	/* Don't free the skb yet */
1508fcd2b5e3SRaghu Vatsavayi }
1509f21fb3edSRaghu Vatsavayi 
1510f21fb3edSRaghu Vatsavayi /**
1511f21fb3edSRaghu Vatsavayi  * liquidio_ptp_adjfine - Adjust ptp frequency
1512f21fb3edSRaghu Vatsavayi  * @ptp: PTP clock info
1513f21fb3edSRaghu Vatsavayi  * @scaled_ppm: how much to adjust by, in scaled parts-per-million
1514e2bd9c76SJacob Keller  *
1515d0ea5cbdSJesse Brandeburg  * Scaled parts per million is ppm with a 16-bit binary fractional field.
1516e2bd9c76SJacob Keller  */
liquidio_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)1517e2bd9c76SJacob Keller static int liquidio_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
1518e2bd9c76SJacob Keller {
1519f21fb3edSRaghu Vatsavayi 	struct lio *lio = container_of(ptp, struct lio, ptp_info);
1520e2bd9c76SJacob Keller 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
1521f21fb3edSRaghu Vatsavayi 	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
1522f21fb3edSRaghu Vatsavayi 	u64 comp, delta;
1523f21fb3edSRaghu Vatsavayi 	unsigned long flags;
1524e2bd9c76SJacob Keller 	bool neg_adj = false;
1525f21fb3edSRaghu Vatsavayi 
1526f21fb3edSRaghu Vatsavayi 	if (ppb < 0) {
1527f21fb3edSRaghu Vatsavayi 		neg_adj = true;
1528f21fb3edSRaghu Vatsavayi 		ppb = -ppb;
1529f21fb3edSRaghu Vatsavayi 	}
1530f21fb3edSRaghu Vatsavayi 
1531f21fb3edSRaghu Vatsavayi 	/* The hardware adds the clock compensation value to the
1532f21fb3edSRaghu Vatsavayi 	 * PTP clock on every coprocessor clock cycle, so we
1533f21fb3edSRaghu Vatsavayi 	 * compute the delta in terms of coprocessor clocks.
1534f21fb3edSRaghu Vatsavayi 	 */
1535f21fb3edSRaghu Vatsavayi 	delta = (u64)ppb << 32;
1536f21fb3edSRaghu Vatsavayi 	do_div(delta, oct->coproc_clock_rate);
1537f21fb3edSRaghu Vatsavayi 
1538f21fb3edSRaghu Vatsavayi 	spin_lock_irqsave(&lio->ptp_lock, flags);
1539f21fb3edSRaghu Vatsavayi 	comp = lio_pci_readq(oct, CN6XXX_MIO_PTP_CLOCK_COMP);
1540f21fb3edSRaghu Vatsavayi 	if (neg_adj)
1541f21fb3edSRaghu Vatsavayi 		comp -= delta;
1542f21fb3edSRaghu Vatsavayi 	else
1543f21fb3edSRaghu Vatsavayi 		comp += delta;
1544f21fb3edSRaghu Vatsavayi 	lio_pci_writeq(oct, comp, CN6XXX_MIO_PTP_CLOCK_COMP);
1545f21fb3edSRaghu Vatsavayi 	spin_unlock_irqrestore(&lio->ptp_lock, flags);
1546f21fb3edSRaghu Vatsavayi 
1547f21fb3edSRaghu Vatsavayi 	return 0;
1548f21fb3edSRaghu Vatsavayi }
1549f21fb3edSRaghu Vatsavayi 
1550f21fb3edSRaghu Vatsavayi /**
1551f21fb3edSRaghu Vatsavayi  * liquidio_ptp_adjtime - Adjust ptp time
1552f21fb3edSRaghu Vatsavayi  * @ptp: PTP clock info
1553f21fb3edSRaghu Vatsavayi  * @delta: how much to adjust by, in nanosecs
1554d0ea5cbdSJesse Brandeburg  */
liquidio_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)1555d0ea5cbdSJesse Brandeburg static int liquidio_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
1556d0ea5cbdSJesse Brandeburg {
1557f21fb3edSRaghu Vatsavayi 	unsigned long flags;
1558f21fb3edSRaghu Vatsavayi 	struct lio *lio = container_of(ptp, struct lio, ptp_info);
1559f21fb3edSRaghu Vatsavayi 
1560f21fb3edSRaghu Vatsavayi 	spin_lock_irqsave(&lio->ptp_lock, flags);
1561f21fb3edSRaghu Vatsavayi 	lio->ptp_adjust += delta;
1562f21fb3edSRaghu Vatsavayi 	spin_unlock_irqrestore(&lio->ptp_lock, flags);
1563f21fb3edSRaghu Vatsavayi 
1564f21fb3edSRaghu Vatsavayi 	return 0;
1565f21fb3edSRaghu Vatsavayi }
1566f21fb3edSRaghu Vatsavayi 
1567f21fb3edSRaghu Vatsavayi /**
1568f21fb3edSRaghu Vatsavayi  * liquidio_ptp_gettime - Get hardware clock time, including any adjustment
1569f21fb3edSRaghu Vatsavayi  * @ptp: PTP clock info
1570f21fb3edSRaghu Vatsavayi  * @ts: timespec
1571d0ea5cbdSJesse Brandeburg  */
liquidio_ptp_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)1572d0ea5cbdSJesse Brandeburg static int liquidio_ptp_gettime(struct ptp_clock_info *ptp,
1573d0ea5cbdSJesse Brandeburg 				struct timespec64 *ts)
1574f21fb3edSRaghu Vatsavayi {
1575f21fb3edSRaghu Vatsavayi 	u64 ns;
1576f21fb3edSRaghu Vatsavayi 	unsigned long flags;
1577f21fb3edSRaghu Vatsavayi 	struct lio *lio = container_of(ptp, struct lio, ptp_info);
1578f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
1579f21fb3edSRaghu Vatsavayi 
1580f21fb3edSRaghu Vatsavayi 	spin_lock_irqsave(&lio->ptp_lock, flags);
1581f21fb3edSRaghu Vatsavayi 	ns = lio_pci_readq(oct, CN6XXX_MIO_PTP_CLOCK_HI);
1582f21fb3edSRaghu Vatsavayi 	ns += lio->ptp_adjust;
1583f21fb3edSRaghu Vatsavayi 	spin_unlock_irqrestore(&lio->ptp_lock, flags);
1584f21fb3edSRaghu Vatsavayi 
1585f21fb3edSRaghu Vatsavayi 	*ts = ns_to_timespec64(ns);
1586f21fb3edSRaghu Vatsavayi 
1587f21fb3edSRaghu Vatsavayi 	return 0;
1588286af315SKefeng Wang }
1589f21fb3edSRaghu Vatsavayi 
1590f21fb3edSRaghu Vatsavayi /**
1591f21fb3edSRaghu Vatsavayi  * liquidio_ptp_settime - Set hardware clock time. Reset adjustment
1592f21fb3edSRaghu Vatsavayi  * @ptp: PTP clock info
1593f21fb3edSRaghu Vatsavayi  * @ts: timespec
1594d0ea5cbdSJesse Brandeburg  */
liquidio_ptp_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)1595d0ea5cbdSJesse Brandeburg static int liquidio_ptp_settime(struct ptp_clock_info *ptp,
1596d0ea5cbdSJesse Brandeburg 				const struct timespec64 *ts)
1597f21fb3edSRaghu Vatsavayi {
1598f21fb3edSRaghu Vatsavayi 	u64 ns;
1599f21fb3edSRaghu Vatsavayi 	unsigned long flags;
1600f21fb3edSRaghu Vatsavayi 	struct lio *lio = container_of(ptp, struct lio, ptp_info);
1601f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
1602f21fb3edSRaghu Vatsavayi 
1603f21fb3edSRaghu Vatsavayi 	ns = timespec64_to_ns(ts);
1604f21fb3edSRaghu Vatsavayi 
1605f21fb3edSRaghu Vatsavayi 	spin_lock_irqsave(&lio->ptp_lock, flags);
1606e7ad9793SArnd Bergmann 	lio_pci_writeq(oct, ns, CN6XXX_MIO_PTP_CLOCK_HI);
1607f21fb3edSRaghu Vatsavayi 	lio->ptp_adjust = 0;
1608f21fb3edSRaghu Vatsavayi 	spin_unlock_irqrestore(&lio->ptp_lock, flags);
1609f21fb3edSRaghu Vatsavayi 
1610f21fb3edSRaghu Vatsavayi 	return 0;
1611f21fb3edSRaghu Vatsavayi }
1612f21fb3edSRaghu Vatsavayi 
1613f21fb3edSRaghu Vatsavayi /**
1614f21fb3edSRaghu Vatsavayi  * liquidio_ptp_enable - Check if PTP is enabled
1615f21fb3edSRaghu Vatsavayi  * @ptp: PTP clock info
1616f21fb3edSRaghu Vatsavayi  * @rq: request
1617d0ea5cbdSJesse Brandeburg  * @on: is it on
1618d0ea5cbdSJesse Brandeburg  */
1619d0ea5cbdSJesse Brandeburg static int
liquidio_ptp_enable(struct ptp_clock_info __maybe_unused * ptp,struct ptp_clock_request __maybe_unused * rq,int __maybe_unused on)1620d0ea5cbdSJesse Brandeburg liquidio_ptp_enable(struct ptp_clock_info __maybe_unused *ptp,
1621f21fb3edSRaghu Vatsavayi 		    struct ptp_clock_request __maybe_unused *rq,
1622a7d5a3dcSRaghu Vatsavayi 		    int __maybe_unused on)
1623d0ea5cbdSJesse Brandeburg {
1624d0ea5cbdSJesse Brandeburg 	return -EOPNOTSUPP;
1625d0ea5cbdSJesse Brandeburg }
1626f21fb3edSRaghu Vatsavayi 
1627f21fb3edSRaghu Vatsavayi /**
1628f21fb3edSRaghu Vatsavayi  * oct_ptp_open - Open PTP clock source
1629f21fb3edSRaghu Vatsavayi  * @netdev: network device
1630f21fb3edSRaghu Vatsavayi  */
oct_ptp_open(struct net_device * netdev)1631d0ea5cbdSJesse Brandeburg static void oct_ptp_open(struct net_device *netdev)
1632d0ea5cbdSJesse Brandeburg {
1633f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
1634f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
1635f21fb3edSRaghu Vatsavayi 
1636f21fb3edSRaghu Vatsavayi 	spin_lock_init(&lio->ptp_lock);
1637f21fb3edSRaghu Vatsavayi 
1638f21fb3edSRaghu Vatsavayi 	snprintf(lio->ptp_info.name, 16, "%s", netdev->name);
1639f21fb3edSRaghu Vatsavayi 	lio->ptp_info.owner = THIS_MODULE;
1640f21fb3edSRaghu Vatsavayi 	lio->ptp_info.max_adj = 250000000;
1641f21fb3edSRaghu Vatsavayi 	lio->ptp_info.n_alarm = 0;
1642f21fb3edSRaghu Vatsavayi 	lio->ptp_info.n_ext_ts = 0;
1643f21fb3edSRaghu Vatsavayi 	lio->ptp_info.n_per_out = 0;
1644f21fb3edSRaghu Vatsavayi 	lio->ptp_info.pps = 0;
1645f21fb3edSRaghu Vatsavayi 	lio->ptp_info.adjfine = liquidio_ptp_adjfine;
1646f21fb3edSRaghu Vatsavayi 	lio->ptp_info.adjtime = liquidio_ptp_adjtime;
1647f21fb3edSRaghu Vatsavayi 	lio->ptp_info.gettime64 = liquidio_ptp_gettime;
1648e2bd9c76SJacob Keller 	lio->ptp_info.settime64 = liquidio_ptp_settime;
1649f21fb3edSRaghu Vatsavayi 	lio->ptp_info.enable = liquidio_ptp_enable;
1650f21fb3edSRaghu Vatsavayi 
1651f21fb3edSRaghu Vatsavayi 	lio->ptp_adjust = 0;
1652f21fb3edSRaghu Vatsavayi 
1653f21fb3edSRaghu Vatsavayi 	lio->ptp_clock = ptp_clock_register(&lio->ptp_info,
1654f21fb3edSRaghu Vatsavayi 					     &oct->pci_dev->dev);
1655f21fb3edSRaghu Vatsavayi 
1656f21fb3edSRaghu Vatsavayi 	if (IS_ERR(lio->ptp_clock))
1657f21fb3edSRaghu Vatsavayi 		lio->ptp_clock = NULL;
1658f21fb3edSRaghu Vatsavayi }
1659f21fb3edSRaghu Vatsavayi 
1660f21fb3edSRaghu Vatsavayi /**
1661f21fb3edSRaghu Vatsavayi  * liquidio_ptp_init - Init PTP clock
1662f21fb3edSRaghu Vatsavayi  * @oct: octeon device
1663f21fb3edSRaghu Vatsavayi  */
liquidio_ptp_init(struct octeon_device * oct)1664d0ea5cbdSJesse Brandeburg static void liquidio_ptp_init(struct octeon_device *oct)
1665d0ea5cbdSJesse Brandeburg {
1666f21fb3edSRaghu Vatsavayi 	u64 clock_comp, cfg;
1667f21fb3edSRaghu Vatsavayi 
1668f21fb3edSRaghu Vatsavayi 	clock_comp = (u64)NSEC_PER_SEC << 32;
1669f21fb3edSRaghu Vatsavayi 	do_div(clock_comp, oct->coproc_clock_rate);
1670f21fb3edSRaghu Vatsavayi 	lio_pci_writeq(oct, clock_comp, CN6XXX_MIO_PTP_CLOCK_COMP);
1671f21fb3edSRaghu Vatsavayi 
1672f21fb3edSRaghu Vatsavayi 	/* Enable */
1673f21fb3edSRaghu Vatsavayi 	cfg = lio_pci_readq(oct, CN6XXX_MIO_PTP_CLOCK_CFG);
1674f21fb3edSRaghu Vatsavayi 	lio_pci_writeq(oct, cfg | 0x01, CN6XXX_MIO_PTP_CLOCK_CFG);
1675f21fb3edSRaghu Vatsavayi }
1676f21fb3edSRaghu Vatsavayi 
1677f21fb3edSRaghu Vatsavayi /**
1678f21fb3edSRaghu Vatsavayi  * load_firmware - Load firmware to device
1679f21fb3edSRaghu Vatsavayi  * @oct: octeon device
1680f21fb3edSRaghu Vatsavayi  *
1681d0ea5cbdSJesse Brandeburg  * Maps device to firmware filename, requests firmware, and downloads it
1682d0ea5cbdSJesse Brandeburg  */
load_firmware(struct octeon_device * oct)1683f21fb3edSRaghu Vatsavayi static int load_firmware(struct octeon_device *oct)
1684f21fb3edSRaghu Vatsavayi {
1685f21fb3edSRaghu Vatsavayi 	int ret = 0;
1686f21fb3edSRaghu Vatsavayi 	const struct firmware *fw;
1687f21fb3edSRaghu Vatsavayi 	char fw_name[LIO_MAX_FW_FILENAME_LEN];
1688f21fb3edSRaghu Vatsavayi 	char *tmp_fw_type;
1689f21fb3edSRaghu Vatsavayi 
1690f21fb3edSRaghu Vatsavayi 	if (fw_type_is_auto()) {
1691f21fb3edSRaghu Vatsavayi 		tmp_fw_type = LIO_FW_NAME_TYPE_NIC;
1692f21fb3edSRaghu Vatsavayi 		strncpy(fw_type, tmp_fw_type, sizeof(fw_type));
1693429cbf6bSRick Farrington 	} else {
1694f21fb3edSRaghu Vatsavayi 		tmp_fw_type = fw_type;
1695429cbf6bSRick Farrington 	}
1696429cbf6bSRick Farrington 
1697f21fb3edSRaghu Vatsavayi 	sprintf(fw_name, "%s%s%s_%s%s", LIO_FW_DIR, LIO_FW_BASE_NAME,
1698429cbf6bSRick Farrington 		octeon_get_conf(oct)->card_name, tmp_fw_type,
1699f21fb3edSRaghu Vatsavayi 		LIO_FW_NAME_SUFFIX);
1700f21fb3edSRaghu Vatsavayi 
1701f21fb3edSRaghu Vatsavayi 	ret = request_firmware(&fw, fw_name, &oct->pci_dev->dev);
1702f21fb3edSRaghu Vatsavayi 	if (ret) {
1703f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Request firmware failed. Could not find file %s.\n",
1704f21fb3edSRaghu Vatsavayi 			fw_name);
1705f21fb3edSRaghu Vatsavayi 		release_firmware(fw);
1706d602de8eSJoe Perches 		return ret;
1707f21fb3edSRaghu Vatsavayi 	}
1708d3d7e6c6SRaghu Vatsavayi 
1709f21fb3edSRaghu Vatsavayi 	ret = octeon_download_firmware(oct, fw->data, fw->size);
1710f21fb3edSRaghu Vatsavayi 
1711f21fb3edSRaghu Vatsavayi 	release_firmware(fw);
1712f21fb3edSRaghu Vatsavayi 
1713f21fb3edSRaghu Vatsavayi 	return ret;
1714f21fb3edSRaghu Vatsavayi }
1715f21fb3edSRaghu Vatsavayi 
1716f21fb3edSRaghu Vatsavayi /**
1717f21fb3edSRaghu Vatsavayi  * octnet_poll_check_txq_status - Poll routine for checking transmit queue status
1718f21fb3edSRaghu Vatsavayi  * @work: work_struct data structure
1719f21fb3edSRaghu Vatsavayi  */
octnet_poll_check_txq_status(struct work_struct * work)1720d0ea5cbdSJesse Brandeburg static void octnet_poll_check_txq_status(struct work_struct *work)
1721d0ea5cbdSJesse Brandeburg {
1722f21fb3edSRaghu Vatsavayi 	struct cavium_wk *wk = (struct cavium_wk *)work;
1723f21fb3edSRaghu Vatsavayi 	struct lio *lio = (struct lio *)wk->ctxptr;
1724f21fb3edSRaghu Vatsavayi 
1725f21fb3edSRaghu Vatsavayi 	if (!ifstate_check(lio, LIO_IFSTATE_RUNNING))
1726f21fb3edSRaghu Vatsavayi 		return;
1727f21fb3edSRaghu Vatsavayi 
1728f21fb3edSRaghu Vatsavayi 	check_txq_status(lio);
1729f21fb3edSRaghu Vatsavayi 	queue_delayed_work(lio->txq_status_wq.wq,
1730f21fb3edSRaghu Vatsavayi 			   &lio->txq_status_wq.wk.work, msecs_to_jiffies(1));
1731f21fb3edSRaghu Vatsavayi }
1732f21fb3edSRaghu Vatsavayi 
1733f21fb3edSRaghu Vatsavayi /**
1734f21fb3edSRaghu Vatsavayi  * setup_tx_poll_fn - Sets up the txq poll check
1735f21fb3edSRaghu Vatsavayi  * @netdev: network device
1736f21fb3edSRaghu Vatsavayi  */
setup_tx_poll_fn(struct net_device * netdev)1737d0ea5cbdSJesse Brandeburg static inline int setup_tx_poll_fn(struct net_device *netdev)
1738d0ea5cbdSJesse Brandeburg {
1739f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
17405b07aee1SRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
1741f21fb3edSRaghu Vatsavayi 
1742f21fb3edSRaghu Vatsavayi 	lio->txq_status_wq.wq = alloc_workqueue("txq-status",
1743f21fb3edSRaghu Vatsavayi 						WQ_MEM_RECLAIM, 0);
1744f21fb3edSRaghu Vatsavayi 	if (!lio->txq_status_wq.wq) {
1745292b9dabSBhaktipriya Shridhar 		dev_err(&oct->pci_dev->dev, "unable to create cavium txq status wq\n");
1746292b9dabSBhaktipriya Shridhar 		return -1;
1747f21fb3edSRaghu Vatsavayi 	}
1748f21fb3edSRaghu Vatsavayi 	INIT_DELAYED_WORK(&lio->txq_status_wq.wk.work,
17495b07aee1SRaghu Vatsavayi 			  octnet_poll_check_txq_status);
1750f21fb3edSRaghu Vatsavayi 	lio->txq_status_wq.wk.ctxptr = lio;
1751f21fb3edSRaghu Vatsavayi 	queue_delayed_work(lio->txq_status_wq.wq,
1752f21fb3edSRaghu Vatsavayi 			   &lio->txq_status_wq.wk.work, msecs_to_jiffies(1));
1753f21fb3edSRaghu Vatsavayi 	return 0;
1754f21fb3edSRaghu Vatsavayi }
1755f21fb3edSRaghu Vatsavayi 
cleanup_tx_poll_fn(struct net_device * netdev)17565b07aee1SRaghu Vatsavayi static inline void cleanup_tx_poll_fn(struct net_device *netdev)
1757f21fb3edSRaghu Vatsavayi {
1758f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
17599a96bde4SRaghu Vatsavayi 
17609a96bde4SRaghu Vatsavayi 	if (lio->txq_status_wq.wq) {
17619a96bde4SRaghu Vatsavayi 		cancel_delayed_work_sync(&lio->txq_status_wq.wk.work);
17629a96bde4SRaghu Vatsavayi 		destroy_workqueue(lio->txq_status_wq.wq);
17635b07aee1SRaghu Vatsavayi 	}
17649a96bde4SRaghu Vatsavayi }
17659a96bde4SRaghu Vatsavayi 
17669a96bde4SRaghu Vatsavayi /**
17675b07aee1SRaghu Vatsavayi  * liquidio_open - Net device open for LiquidIO
17689a96bde4SRaghu Vatsavayi  * @netdev: network device
1769f21fb3edSRaghu Vatsavayi  */
liquidio_open(struct net_device * netdev)1770d0ea5cbdSJesse Brandeburg static int liquidio_open(struct net_device *netdev)
1771d0ea5cbdSJesse Brandeburg {
1772f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
1773f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
1774f21fb3edSRaghu Vatsavayi 	struct octeon_device_priv *oct_priv = oct->priv;
1775f21fb3edSRaghu Vatsavayi 	struct napi_struct *napi, *n;
1776f21fb3edSRaghu Vatsavayi 	int ret = 0;
1777fe2d22b1SIntiyaz Basha 
1778fe2d22b1SIntiyaz Basha 	if (oct->props[lio->ifidx].napi_enabled == 0) {
1779f21fb3edSRaghu Vatsavayi 		tasklet_disable(&oct_priv->droq_tasklet);
1780dbc97bfdSTom Seewald 
1781f21fb3edSRaghu Vatsavayi 		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
17829a96bde4SRaghu Vatsavayi 			napi_enable(napi);
1783fe2d22b1SIntiyaz Basha 
1784fe2d22b1SIntiyaz Basha 		oct->props[lio->ifidx].napi_enabled = 1;
1785f21fb3edSRaghu Vatsavayi 
1786f21fb3edSRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(oct))
1787f21fb3edSRaghu Vatsavayi 			oct->droq[0]->ops.poll_mode = 1;
17889a96bde4SRaghu Vatsavayi 	}
17897b6b6c95SRaghu Vatsavayi 
17907b6b6c95SRaghu Vatsavayi 	if (oct->ptp_enable)
17917b6b6c95SRaghu Vatsavayi 		oct_ptp_open(netdev);
17929a96bde4SRaghu Vatsavayi 
17939a96bde4SRaghu Vatsavayi 	ifstate_set(lio, LIO_IFSTATE_RUNNING);
1794aa69ff9eSIntiyaz Basha 
1795f21fb3edSRaghu Vatsavayi 	if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on) {
1796f21fb3edSRaghu Vatsavayi 		ret = setup_tx_poll_fn(netdev);
1797f21fb3edSRaghu Vatsavayi 		if (ret)
17989a96bde4SRaghu Vatsavayi 			goto err_poll;
1799*733d4bbfSLeon Romanovsky 	}
18008979f428SZhengchao Shao 
18018979f428SZhengchao Shao 	netif_tx_start_all_queues(netdev);
18028979f428SZhengchao Shao 
18035b07aee1SRaghu Vatsavayi 	/* Ready for link status updates */
18049a96bde4SRaghu Vatsavayi 	lio->intf_open = 1;
1805c33c9973SIntiyaz Basha 
1806c33c9973SIntiyaz Basha 	netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
1807c33c9973SIntiyaz Basha 
1808c33c9973SIntiyaz Basha 	/* tell Octeon to start forwarding packets to host */
1809c33c9973SIntiyaz Basha 	ret = send_rx_ctrl_cmd(lio, 1);
1810c33c9973SIntiyaz Basha 	if (ret)
1811f21fb3edSRaghu Vatsavayi 		goto err_rx_ctrl;
1812f21fb3edSRaghu Vatsavayi 
1813dbc97bfdSTom Seewald 	/* start periodical statistics fetch */
1814dbc97bfdSTom Seewald 	INIT_DELAYED_WORK(&lio->stats_wk.work, lio_fetch_stats);
18158979f428SZhengchao Shao 	lio->stats_wk.ctxptr = lio;
1816f21fb3edSRaghu Vatsavayi 	schedule_delayed_work(&lio->stats_wk.work, msecs_to_jiffies
181735878618SPradeep Nalla 					(LIQUIDIO_NDEV_STATS_POLL_TIME_MS));
181835878618SPradeep Nalla 
181935878618SPradeep Nalla 	dev_info(&oct->pci_dev->dev, "%s interface is opened\n",
182035878618SPradeep Nalla 		 netdev->name);
182135878618SPradeep Nalla 
182235878618SPradeep Nalla 	return 0;
1823f21fb3edSRaghu Vatsavayi 
1824f21fb3edSRaghu Vatsavayi err_rx_ctrl:
1825f21fb3edSRaghu Vatsavayi 	if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on)
18268979f428SZhengchao Shao 		cleanup_tx_poll_fn(netdev);
18278979f428SZhengchao Shao err_poll:
18288979f428SZhengchao Shao 	if (lio->ptp_clock) {
1829*733d4bbfSLeon Romanovsky 		ptp_clock_unregister(lio->ptp_clock);
18308979f428SZhengchao Shao 		lio->ptp_clock = NULL;
18318979f428SZhengchao Shao 	}
18328979f428SZhengchao Shao 
18338979f428SZhengchao Shao 	if (oct->props[lio->ifidx].napi_enabled == 1) {
18348979f428SZhengchao Shao 		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
18358979f428SZhengchao Shao 			napi_disable(napi);
18368979f428SZhengchao Shao 
18378979f428SZhengchao Shao 		oct->props[lio->ifidx].napi_enabled = 0;
18388979f428SZhengchao Shao 
18398979f428SZhengchao Shao 		if (OCTEON_CN23XX_PF(oct))
18408979f428SZhengchao Shao 			oct->droq[0]->ops.poll_mode = 0;
18418979f428SZhengchao Shao 	}
18428979f428SZhengchao Shao 
18438979f428SZhengchao Shao 	return ret;
18448979f428SZhengchao Shao }
18458979f428SZhengchao Shao 
18468979f428SZhengchao Shao /**
1847dbc97bfdSTom Seewald  * liquidio_stop - Net device stop for LiquidIO
1848f21fb3edSRaghu Vatsavayi  * @netdev: network device
1849f21fb3edSRaghu Vatsavayi  */
liquidio_stop(struct net_device * netdev)1850f21fb3edSRaghu Vatsavayi static int liquidio_stop(struct net_device *netdev)
1851d0ea5cbdSJesse Brandeburg {
1852d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
1853f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
1854f21fb3edSRaghu Vatsavayi 	struct octeon_device_priv *oct_priv = oct->priv;
1855f21fb3edSRaghu Vatsavayi 	struct napi_struct *napi, *n;
1856f21fb3edSRaghu Vatsavayi 	int ret = 0;
1857f21fb3edSRaghu Vatsavayi 
1858fe2d22b1SIntiyaz Basha 	ifstate_reset(lio, LIO_IFSTATE_RUNNING);
1859fe2d22b1SIntiyaz Basha 
186042013e90SIntiyaz Basha 	/* Stop any link updates */
1861dbc97bfdSTom Seewald 	lio->intf_open = 0;
186242013e90SIntiyaz Basha 
18639a96bde4SRaghu Vatsavayi 	stop_txqs(netdev);
18649a96bde4SRaghu Vatsavayi 
1865c33c9973SIntiyaz Basha 	/* Inform that netif carrier is down */
1866c33c9973SIntiyaz Basha 	netif_carrier_off(netdev);
1867c33c9973SIntiyaz Basha 	netif_tx_disable(netdev);
1868c33c9973SIntiyaz Basha 
18699a96bde4SRaghu Vatsavayi 	lio->linfo.link.s.link_up = 0;
1870f21fb3edSRaghu Vatsavayi 	lio->link_changes++;
18719a96bde4SRaghu Vatsavayi 
1872c33c9973SIntiyaz Basha 	/* Tell Octeon that nic interface is down. */
1873c33c9973SIntiyaz Basha 	ret = send_rx_ctrl_cmd(lio, 0);
18740cece6c5SRaghu Vatsavayi 	if (ret)
18750cece6c5SRaghu Vatsavayi 		return ret;
1876f21fb3edSRaghu Vatsavayi 
1877cb2336b5SFelix Manlunas 	if (OCTEON_CN23XX_PF(oct)) {
1878dbc97bfdSTom Seewald 		if (!oct->msix_on)
1879dbc97bfdSTom Seewald 			cleanup_tx_poll_fn(netdev);
1880dbc97bfdSTom Seewald 	} else {
1881f21fb3edSRaghu Vatsavayi 		cleanup_tx_poll_fn(netdev);
18825b07aee1SRaghu Vatsavayi 	}
18835b07aee1SRaghu Vatsavayi 
18849a96bde4SRaghu Vatsavayi 	cancel_delayed_work_sync(&lio->stats_wk.work);
18855b07aee1SRaghu Vatsavayi 
18865b07aee1SRaghu Vatsavayi 	if (lio->ptp_clock) {
18875b07aee1SRaghu Vatsavayi 		ptp_clock_unregister(lio->ptp_clock);
1888f21fb3edSRaghu Vatsavayi 		lio->ptp_clock = NULL;
188935878618SPradeep Nalla 	}
189035878618SPradeep Nalla 
1891f21fb3edSRaghu Vatsavayi 	/* Wait for any pending Rx descriptors */
1892f21fb3edSRaghu Vatsavayi 	if (lio_wait_for_clean_oq(oct))
1893f21fb3edSRaghu Vatsavayi 		netif_info(lio, rx_err, lio->netdev,
1894f21fb3edSRaghu Vatsavayi 			   "Proceeding with stop interface after partial RX desc processing\n");
1895f21fb3edSRaghu Vatsavayi 
1896ccdd0b4cSRaghu Vatsavayi 	if (oct->props[lio->ifidx].napi_enabled == 1) {
1897ccdd0b4cSRaghu Vatsavayi 		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
1898ccdd0b4cSRaghu Vatsavayi 			napi_disable(napi);
1899ccdd0b4cSRaghu Vatsavayi 
1900ccdd0b4cSRaghu Vatsavayi 		oct->props[lio->ifidx].napi_enabled = 0;
1901ccdd0b4cSRaghu Vatsavayi 
1902ccdd0b4cSRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(oct))
1903ccdd0b4cSRaghu Vatsavayi 			oct->droq[0]->ops.poll_mode = 0;
1904ccdd0b4cSRaghu Vatsavayi 
1905ccdd0b4cSRaghu Vatsavayi 		tasklet_enable(&oct_priv->droq_tasklet);
1906ccdd0b4cSRaghu Vatsavayi 	}
1907ccdd0b4cSRaghu Vatsavayi 
1908ccdd0b4cSRaghu Vatsavayi 	dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
1909fe2d22b1SIntiyaz Basha 
1910fe2d22b1SIntiyaz Basha 	return ret;
1911ccdd0b4cSRaghu Vatsavayi }
1912ccdd0b4cSRaghu Vatsavayi 
1913f21fb3edSRaghu Vatsavayi /**
1914f21fb3edSRaghu Vatsavayi  * get_new_flags - Converts a mask based on net device flags
1915dbc97bfdSTom Seewald  * @netdev: network device
1916f21fb3edSRaghu Vatsavayi  *
1917f21fb3edSRaghu Vatsavayi  * This routine generates a octnet_ifflags mask from the net device flags
1918f21fb3edSRaghu Vatsavayi  * received from the OS.
1919d0ea5cbdSJesse Brandeburg  */
get_new_flags(struct net_device * netdev)1920d0ea5cbdSJesse Brandeburg static inline enum octnet_ifflags get_new_flags(struct net_device *netdev)
1921f21fb3edSRaghu Vatsavayi {
1922f21fb3edSRaghu Vatsavayi 	enum octnet_ifflags f = OCTNET_IFFLAG_UNICAST;
1923f21fb3edSRaghu Vatsavayi 
1924f21fb3edSRaghu Vatsavayi 	if (netdev->flags & IFF_PROMISC)
1925f21fb3edSRaghu Vatsavayi 		f |= OCTNET_IFFLAG_PROMISC;
1926f21fb3edSRaghu Vatsavayi 
1927f21fb3edSRaghu Vatsavayi 	if (netdev->flags & IFF_ALLMULTI)
1928f21fb3edSRaghu Vatsavayi 		f |= OCTNET_IFFLAG_ALLMULTI;
1929f21fb3edSRaghu Vatsavayi 
1930f21fb3edSRaghu Vatsavayi 	if (netdev->flags & IFF_MULTICAST) {
1931f21fb3edSRaghu Vatsavayi 		f |= OCTNET_IFFLAG_MULTICAST;
1932f21fb3edSRaghu Vatsavayi 
1933f21fb3edSRaghu Vatsavayi 		/* Accept all multicast addresses if there are more than we
1934f21fb3edSRaghu Vatsavayi 		 * can handle
1935f21fb3edSRaghu Vatsavayi 		 */
1936f21fb3edSRaghu Vatsavayi 		if (netdev_mc_count(netdev) > MAX_OCTEON_MULTICAST_ADDR)
1937f21fb3edSRaghu Vatsavayi 			f |= OCTNET_IFFLAG_ALLMULTI;
1938f21fb3edSRaghu Vatsavayi 	}
1939f21fb3edSRaghu Vatsavayi 
1940f21fb3edSRaghu Vatsavayi 	if (netdev->flags & IFF_BROADCAST)
1941f21fb3edSRaghu Vatsavayi 		f |= OCTNET_IFFLAG_BROADCAST;
1942f21fb3edSRaghu Vatsavayi 
1943f21fb3edSRaghu Vatsavayi 	return f;
1944f21fb3edSRaghu Vatsavayi }
1945f21fb3edSRaghu Vatsavayi 
1946f21fb3edSRaghu Vatsavayi /**
1947f21fb3edSRaghu Vatsavayi  * liquidio_set_mcast_list - Net device set_multicast_list
1948f21fb3edSRaghu Vatsavayi  * @netdev: network device
1949f21fb3edSRaghu Vatsavayi  */
liquidio_set_mcast_list(struct net_device * netdev)1950f21fb3edSRaghu Vatsavayi static void liquidio_set_mcast_list(struct net_device *netdev)
1951f21fb3edSRaghu Vatsavayi {
1952d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
1953d0ea5cbdSJesse Brandeburg 	struct octeon_device *oct = lio->oct_dev;
1954f21fb3edSRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
1955f21fb3edSRaghu Vatsavayi 	struct netdev_hw_addr *ha;
1956f21fb3edSRaghu Vatsavayi 	u64 *mc;
1957f21fb3edSRaghu Vatsavayi 	int ret;
1958f21fb3edSRaghu Vatsavayi 	int mc_count = min(netdev_mc_count(netdev), MAX_OCTEON_MULTICAST_ADDR);
1959f21fb3edSRaghu Vatsavayi 
1960f21fb3edSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
1961f21fb3edSRaghu Vatsavayi 
1962a7d5a3dcSRaghu Vatsavayi 	/* Create a ctrl pkt command to be sent to core app. */
1963f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
1964f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_MULTI_LIST;
1965f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.param1 = get_new_flags(netdev);
1966f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.param2 = mc_count;
1967f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.more = mc_count;
1968f21fb3edSRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
1969f21fb3edSRaghu Vatsavayi 	nctrl.netpndev = (u64)netdev;
19700cece6c5SRaghu Vatsavayi 	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
19710cece6c5SRaghu Vatsavayi 
1972f21fb3edSRaghu Vatsavayi 	/* copy all the addresses into the udd */
19730cece6c5SRaghu Vatsavayi 	mc = &nctrl.udd[0];
1974f21fb3edSRaghu Vatsavayi 	netdev_for_each_mc_addr(ha, netdev) {
1975f21fb3edSRaghu Vatsavayi 		*mc = 0;
1976f21fb3edSRaghu Vatsavayi 		memcpy(((u8 *)mc) + 2, ha->addr, ETH_ALEN);
1977f21fb3edSRaghu Vatsavayi 		/* no need to swap bytes */
1978f21fb3edSRaghu Vatsavayi 
1979f21fb3edSRaghu Vatsavayi 		if (++mc > &nctrl.udd[mc_count])
1980f21fb3edSRaghu Vatsavayi 			break;
1981f21fb3edSRaghu Vatsavayi 	}
1982f21fb3edSRaghu Vatsavayi 
1983f21fb3edSRaghu Vatsavayi 	/* Apparently, any activity in this call from the kernel has to
1984f21fb3edSRaghu Vatsavayi 	 * be atomic. So we won't wait for response.
1985f21fb3edSRaghu Vatsavayi 	 */
1986f21fb3edSRaghu Vatsavayi 
1987f21fb3edSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
1988f21fb3edSRaghu Vatsavayi 	if (ret) {
1989f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n",
1990f21fb3edSRaghu Vatsavayi 			ret);
1991f21fb3edSRaghu Vatsavayi 	}
19920cece6c5SRaghu Vatsavayi }
1993edd572d7SFelix Manlunas 
1994f21fb3edSRaghu Vatsavayi /**
1995f21fb3edSRaghu Vatsavayi  * liquidio_set_mac - Net device set_mac_address
1996f21fb3edSRaghu Vatsavayi  * @netdev: network device
1997f21fb3edSRaghu Vatsavayi  * @p: pointer to sockaddr
1998f21fb3edSRaghu Vatsavayi  */
liquidio_set_mac(struct net_device * netdev,void * p)1999f21fb3edSRaghu Vatsavayi static int liquidio_set_mac(struct net_device *netdev, void *p)
2000d0ea5cbdSJesse Brandeburg {
2001d0ea5cbdSJesse Brandeburg 	int ret = 0;
2002d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
2003f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
2004f21fb3edSRaghu Vatsavayi 	struct sockaddr *addr = (struct sockaddr *)p;
2005f21fb3edSRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
2006f21fb3edSRaghu Vatsavayi 
2007f21fb3edSRaghu Vatsavayi 	if (!is_valid_ether_addr(addr->sa_data))
2008f21fb3edSRaghu Vatsavayi 		return -EADDRNOTAVAIL;
2009f21fb3edSRaghu Vatsavayi 
2010f21fb3edSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
2011f21fb3edSRaghu Vatsavayi 
20120cece6c5SRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
2013f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
2014f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.param1 = 0;
2015f21fb3edSRaghu Vatsavayi 	nctrl.ncmd.s.more = 1;
2016f21fb3edSRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
2017f21fb3edSRaghu Vatsavayi 	nctrl.netpndev = (u64)netdev;
2018f21fb3edSRaghu Vatsavayi 
20190cece6c5SRaghu Vatsavayi 	nctrl.udd[0] = 0;
2020f21fb3edSRaghu Vatsavayi 	/* The MAC Address is presented in network byte order. */
20210cece6c5SRaghu Vatsavayi 	memcpy((u8 *)&nctrl.udd[0] + 2, addr->sa_data, ETH_ALEN);
2022f21fb3edSRaghu Vatsavayi 
2023f21fb3edSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
2024f21fb3edSRaghu Vatsavayi 	if (ret < 0) {
2025f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "MAC Address change failed\n");
2026f21fb3edSRaghu Vatsavayi 		return -ENOMEM;
2027f21fb3edSRaghu Vatsavayi 	}
20280cece6c5SRaghu Vatsavayi 
2029f21fb3edSRaghu Vatsavayi 	if (nctrl.sc_status) {
2030f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev,
2031f21fb3edSRaghu Vatsavayi 			"%s: MAC Address change failed. sc return=%x\n",
2032f21fb3edSRaghu Vatsavayi 			 __func__, nctrl.sc_status);
2033edd572d7SFelix Manlunas 		return -EIO;
2034edd572d7SFelix Manlunas 	}
2035edd572d7SFelix Manlunas 
2036edd572d7SFelix Manlunas 	eth_hw_addr_set(netdev, addr->sa_data);
2037edd572d7SFelix Manlunas 	memcpy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data, ETH_ALEN);
2038edd572d7SFelix Manlunas 
2039edd572d7SFelix Manlunas 	return 0;
2040edd572d7SFelix Manlunas }
2041a05e4c0aSJakub Kicinski 
2042f21fb3edSRaghu Vatsavayi static void
liquidio_get_stats64(struct net_device * netdev,struct rtnl_link_stats64 * lstats)2043f21fb3edSRaghu Vatsavayi liquidio_get_stats64(struct net_device *netdev,
2044f21fb3edSRaghu Vatsavayi 		     struct rtnl_link_stats64 *lstats)
2045f21fb3edSRaghu Vatsavayi {
2046f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
204780002347SPradeep Nalla 	struct octeon_device *oct;
204880002347SPradeep Nalla 	u64 pkts = 0, drop = 0, bytes = 0;
204980002347SPradeep Nalla 	struct oct_droq_stats *oq_stats;
2050f21fb3edSRaghu Vatsavayi 	struct oct_iq_stats *iq_stats;
2051f21fb3edSRaghu Vatsavayi 	int i, iq_no, oq_no;
2052f21fb3edSRaghu Vatsavayi 
2053f21fb3edSRaghu Vatsavayi 	oct = lio->oct_dev;
2054f21fb3edSRaghu Vatsavayi 
2055f21fb3edSRaghu Vatsavayi 	if (ifstate_check(lio, LIO_IFSTATE_RESETTING))
2056f21fb3edSRaghu Vatsavayi 		return;
2057f21fb3edSRaghu Vatsavayi 
2058f21fb3edSRaghu Vatsavayi 	for (i = 0; i < oct->num_iqs; i++) {
2059f21fb3edSRaghu Vatsavayi 		iq_no = lio->linfo.txpciq[i].s.q_no;
2060d18ca7dfSIntiyaz Basha 		iq_stats = &oct->instr_queue[iq_no]->stats;
206180002347SPradeep Nalla 		pkts += iq_stats->tx_done;
2062d18ca7dfSIntiyaz Basha 		drop += iq_stats->tx_dropped;
2063a82457f1SIntiyaz Basha 		bytes += iq_stats->tx_tot_bytes;
206426236fa9SRaghu Vatsavayi 	}
2065f21fb3edSRaghu Vatsavayi 
2066f21fb3edSRaghu Vatsavayi 	lstats->tx_packets = pkts;
2067f21fb3edSRaghu Vatsavayi 	lstats->tx_bytes = bytes;
2068f21fb3edSRaghu Vatsavayi 	lstats->tx_dropped = drop;
2069f21fb3edSRaghu Vatsavayi 
2070f21fb3edSRaghu Vatsavayi 	pkts = 0;
207180002347SPradeep Nalla 	drop = 0;
207280002347SPradeep Nalla 	bytes = 0;
207380002347SPradeep Nalla 
2074f21fb3edSRaghu Vatsavayi 	for (i = 0; i < oct->num_oqs; i++) {
2075f21fb3edSRaghu Vatsavayi 		oq_no = lio->linfo.rxpciq[i].s.q_no;
2076f21fb3edSRaghu Vatsavayi 		oq_stats = &oct->droq[oq_no]->stats;
2077f21fb3edSRaghu Vatsavayi 		pkts += oq_stats->rx_pkts_received;
2078f21fb3edSRaghu Vatsavayi 		drop += (oq_stats->rx_dropped +
2079a82457f1SIntiyaz Basha 			 oq_stats->dropped_nodispatch +
208026236fa9SRaghu Vatsavayi 			 oq_stats->dropped_toomany +
2081f21fb3edSRaghu Vatsavayi 			 oq_stats->dropped_nomem);
2082f21fb3edSRaghu Vatsavayi 		bytes += oq_stats->rx_bytes_received;
2083f21fb3edSRaghu Vatsavayi 	}
2084f21fb3edSRaghu Vatsavayi 
2085f21fb3edSRaghu Vatsavayi 	lstats->rx_bytes = bytes;
2086f21fb3edSRaghu Vatsavayi 	lstats->rx_packets = pkts;
2087f21fb3edSRaghu Vatsavayi 	lstats->rx_dropped = drop;
2088f21fb3edSRaghu Vatsavayi 
2089f21fb3edSRaghu Vatsavayi 	lstats->multicast = oct->link_stats.fromwire.fw_total_mcast;
209080002347SPradeep Nalla 	lstats->collisions = oct->link_stats.fromhost.total_collisions;
209180002347SPradeep Nalla 
209280002347SPradeep Nalla 	/* detailed rx_errors: */
2093f21fb3edSRaghu Vatsavayi 	lstats->rx_length_errors = oct->link_stats.fromwire.l2_err;
209480002347SPradeep Nalla 	/* recved pkt with crc error    */
209580002347SPradeep Nalla 	lstats->rx_crc_errors = oct->link_stats.fromwire.fcs_err;
209680002347SPradeep Nalla 	/* recv'd frame alignment error */
209780002347SPradeep Nalla 	lstats->rx_frame_errors = oct->link_stats.fromwire.frame_err;
209880002347SPradeep Nalla 	/* recv'r fifo overrun */
209980002347SPradeep Nalla 	lstats->rx_fifo_errors = oct->link_stats.fromwire.fifo_err;
210080002347SPradeep Nalla 
210180002347SPradeep Nalla 	lstats->rx_errors = lstats->rx_length_errors + lstats->rx_crc_errors +
210280002347SPradeep Nalla 		lstats->rx_frame_errors + lstats->rx_fifo_errors;
210380002347SPradeep Nalla 
210480002347SPradeep Nalla 	/* detailed tx_errors */
210580002347SPradeep Nalla 	lstats->tx_aborted_errors = oct->link_stats.fromhost.fw_err_pko;
210680002347SPradeep Nalla 	lstats->tx_carrier_errors = oct->link_stats.fromhost.fw_err_link;
210780002347SPradeep Nalla 	lstats->tx_fifo_errors = oct->link_stats.fromhost.fifo_err;
210880002347SPradeep Nalla 
210980002347SPradeep Nalla 	lstats->tx_errors = lstats->tx_aborted_errors +
211080002347SPradeep Nalla 		lstats->tx_carrier_errors +
211180002347SPradeep Nalla 		lstats->tx_fifo_errors;
211280002347SPradeep Nalla }
211380002347SPradeep Nalla 
211480002347SPradeep Nalla /**
211580002347SPradeep Nalla  * hwtstamp_ioctl - Handler for SIOCSHWTSTAMP ioctl
211680002347SPradeep Nalla  * @netdev: network device
2117f21fb3edSRaghu Vatsavayi  * @ifr: interface request
2118f21fb3edSRaghu Vatsavayi  */
hwtstamp_ioctl(struct net_device * netdev,struct ifreq * ifr)2119f21fb3edSRaghu Vatsavayi static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
2120d0ea5cbdSJesse Brandeburg {
2121d0ea5cbdSJesse Brandeburg 	struct hwtstamp_config conf;
2122d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
2123f21fb3edSRaghu Vatsavayi 
2124a7d5a3dcSRaghu Vatsavayi 	if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf)))
2125f21fb3edSRaghu Vatsavayi 		return -EFAULT;
2126f21fb3edSRaghu Vatsavayi 
2127f21fb3edSRaghu Vatsavayi 	switch (conf.tx_type) {
2128f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_TX_ON:
2129f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_TX_OFF:
2130f21fb3edSRaghu Vatsavayi 		break;
2131f21fb3edSRaghu Vatsavayi 	default:
2132f21fb3edSRaghu Vatsavayi 		return -ERANGE;
2133f21fb3edSRaghu Vatsavayi 	}
2134f21fb3edSRaghu Vatsavayi 
2135f21fb3edSRaghu Vatsavayi 	switch (conf.rx_filter) {
2136f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_NONE:
2137f21fb3edSRaghu Vatsavayi 		break;
2138f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_ALL:
2139f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_SOME:
2140f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
2141f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
2142f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
2143f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
2144f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
2145f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
2146f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
2147f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
2148f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
2149f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
2150f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
2151f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
2152f21fb3edSRaghu Vatsavayi 	case HWTSTAMP_FILTER_NTP_ALL:
2153f21fb3edSRaghu Vatsavayi 		conf.rx_filter = HWTSTAMP_FILTER_ALL;
2154f21fb3edSRaghu Vatsavayi 		break;
2155f21fb3edSRaghu Vatsavayi 	default:
2156f21fb3edSRaghu Vatsavayi 		return -ERANGE;
2157e3412575SMiroslav Lichvar 	}
2158f21fb3edSRaghu Vatsavayi 
2159f21fb3edSRaghu Vatsavayi 	if (conf.rx_filter == HWTSTAMP_FILTER_ALL)
2160f21fb3edSRaghu Vatsavayi 		ifstate_set(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED);
2161f21fb3edSRaghu Vatsavayi 
2162f21fb3edSRaghu Vatsavayi 	else
2163f21fb3edSRaghu Vatsavayi 		ifstate_reset(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED);
2164f21fb3edSRaghu Vatsavayi 
2165f21fb3edSRaghu Vatsavayi 	return copy_to_user(ifr->ifr_data, &conf, sizeof(conf)) ? -EFAULT : 0;
2166f21fb3edSRaghu Vatsavayi }
2167f21fb3edSRaghu Vatsavayi 
2168f21fb3edSRaghu Vatsavayi /**
2169f21fb3edSRaghu Vatsavayi  * liquidio_ioctl - ioctl handler
2170f21fb3edSRaghu Vatsavayi  * @netdev: network device
2171f21fb3edSRaghu Vatsavayi  * @ifr: interface request
2172f21fb3edSRaghu Vatsavayi  * @cmd: command
2173f21fb3edSRaghu Vatsavayi  */
liquidio_ioctl(struct net_device * netdev,struct ifreq * ifr,int cmd)2174d0ea5cbdSJesse Brandeburg static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
2175d0ea5cbdSJesse Brandeburg {
2176d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
2177d0ea5cbdSJesse Brandeburg 
2178f21fb3edSRaghu Vatsavayi 	switch (cmd) {
2179f21fb3edSRaghu Vatsavayi 	case SIOCSHWTSTAMP:
2180f21fb3edSRaghu Vatsavayi 		if (lio->oct_dev->ptp_enable)
21819feb16aeSPrasad Kanneganti 			return hwtstamp_ioctl(netdev, ifr);
21829feb16aeSPrasad Kanneganti 		fallthrough;
2183f21fb3edSRaghu Vatsavayi 	default:
2184f21fb3edSRaghu Vatsavayi 		return -EOPNOTSUPP;
2185aa69ff9eSIntiyaz Basha 	}
2186a7d5a3dcSRaghu Vatsavayi }
2187df561f66SGustavo A. R. Silva 
2188f21fb3edSRaghu Vatsavayi /**
2189f21fb3edSRaghu Vatsavayi  * handle_timestamp - handle a Tx timestamp response
2190f21fb3edSRaghu Vatsavayi  * @oct: octeon device
2191f21fb3edSRaghu Vatsavayi  * @status: response status
2192f21fb3edSRaghu Vatsavayi  * @buf: pointer to skb
2193f21fb3edSRaghu Vatsavayi  */
handle_timestamp(struct octeon_device * oct,u32 status,void * buf)2194d0ea5cbdSJesse Brandeburg static void handle_timestamp(struct octeon_device *oct,
2195d0ea5cbdSJesse Brandeburg 			     u32 status,
2196d0ea5cbdSJesse Brandeburg 			     void *buf)
2197d0ea5cbdSJesse Brandeburg {
2198f21fb3edSRaghu Vatsavayi 	struct octnet_buf_free_info *finfo;
2199f21fb3edSRaghu Vatsavayi 	struct octeon_soft_command *sc;
2200f21fb3edSRaghu Vatsavayi 	struct oct_timestamp_resp *resp;
2201f21fb3edSRaghu Vatsavayi 	struct lio *lio;
2202f21fb3edSRaghu Vatsavayi 	struct sk_buff *skb = (struct sk_buff *)buf;
2203f21fb3edSRaghu Vatsavayi 
2204f21fb3edSRaghu Vatsavayi 	finfo = (struct octnet_buf_free_info *)skb->cb;
2205f21fb3edSRaghu Vatsavayi 	lio = finfo->lio;
2206f21fb3edSRaghu Vatsavayi 	sc = finfo->sc;
2207f21fb3edSRaghu Vatsavayi 	oct = lio->oct_dev;
2208f21fb3edSRaghu Vatsavayi 	resp = (struct oct_timestamp_resp *)sc->virtrptr;
2209f21fb3edSRaghu Vatsavayi 
2210f21fb3edSRaghu Vatsavayi 	if (status != OCTEON_REQUEST_DONE) {
2211f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Tx timestamp instruction failed. Status: %llx\n",
2212f21fb3edSRaghu Vatsavayi 			CVM_CAST64(status));
2213f21fb3edSRaghu Vatsavayi 		resp->timestamp = 0;
2214f21fb3edSRaghu Vatsavayi 	}
2215f21fb3edSRaghu Vatsavayi 
2216f21fb3edSRaghu Vatsavayi 	octeon_swap_8B_data(&resp->timestamp, 1);
2217f21fb3edSRaghu Vatsavayi 
2218f21fb3edSRaghu Vatsavayi 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) != 0)) {
2219f21fb3edSRaghu Vatsavayi 		struct skb_shared_hwtstamps ts;
2220f21fb3edSRaghu Vatsavayi 		u64 ns = resp->timestamp;
2221f21fb3edSRaghu Vatsavayi 
2222f21fb3edSRaghu Vatsavayi 		netif_info(lio, tx_done, lio->netdev,
222319a6d156SColin Ian King 			   "Got resulting SKBTX_HW_TSTAMP skb=%p ns=%016llu\n",
2224f21fb3edSRaghu Vatsavayi 			   skb, (unsigned long long)ns);
2225f21fb3edSRaghu Vatsavayi 		ts.hwtstamp = ns_to_ktime(ns + lio->ptp_adjust);
2226f21fb3edSRaghu Vatsavayi 		skb_tstamp_tx(skb, &ts);
2227f21fb3edSRaghu Vatsavayi 	}
2228f21fb3edSRaghu Vatsavayi 
2229f21fb3edSRaghu Vatsavayi 	octeon_free_soft_command(oct, sc);
2230f21fb3edSRaghu Vatsavayi 	tx_buffer_free(skb);
2231f21fb3edSRaghu Vatsavayi }
2232f21fb3edSRaghu Vatsavayi 
2233f21fb3edSRaghu Vatsavayi /**
2234f21fb3edSRaghu Vatsavayi  * send_nic_timestamp_pkt - Send a data packet that will be timestamped
2235cabeb13bSRaghu Vatsavayi  * @oct: octeon device
2236f21fb3edSRaghu Vatsavayi  * @ndata: pointer to network data
2237f21fb3edSRaghu Vatsavayi  * @finfo: pointer to private network data
2238d0ea5cbdSJesse Brandeburg  * @xmit_more: more is coming
2239d0ea5cbdSJesse Brandeburg  */
send_nic_timestamp_pkt(struct octeon_device * oct,struct octnic_data_pkt * ndata,struct octnet_buf_free_info * finfo,int xmit_more)2240d0ea5cbdSJesse Brandeburg static inline int send_nic_timestamp_pkt(struct octeon_device *oct,
2241d0ea5cbdSJesse Brandeburg 					 struct octnic_data_pkt *ndata,
2242d0ea5cbdSJesse Brandeburg 					 struct octnet_buf_free_info *finfo,
2243d0ea5cbdSJesse Brandeburg 					 int xmit_more)
2244f21fb3edSRaghu Vatsavayi {
2245f21fb3edSRaghu Vatsavayi 	int retval;
2246f21fb3edSRaghu Vatsavayi 	struct octeon_soft_command *sc;
2247c859e21aSIntiyaz Basha 	struct lio *lio;
2248c859e21aSIntiyaz Basha 	int ring_doorbell;
2249f21fb3edSRaghu Vatsavayi 	u32 len;
2250f21fb3edSRaghu Vatsavayi 
2251f21fb3edSRaghu Vatsavayi 	lio = finfo->lio;
2252f21fb3edSRaghu Vatsavayi 
2253f21fb3edSRaghu Vatsavayi 	sc = octeon_alloc_soft_command_resp(oct, &ndata->cmd,
22546a885b60SRaghu Vatsavayi 					    sizeof(struct oct_timestamp_resp));
2255f21fb3edSRaghu Vatsavayi 	finfo->sc = sc;
2256f21fb3edSRaghu Vatsavayi 
2257f21fb3edSRaghu Vatsavayi 	if (!sc) {
2258f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "No memory for timestamped data packet\n");
2259f21fb3edSRaghu Vatsavayi 		return IQ_SEND_FAILED;
2260f21fb3edSRaghu Vatsavayi 	}
2261f21fb3edSRaghu Vatsavayi 
2262f21fb3edSRaghu Vatsavayi 	if (ndata->reqtype == REQTYPE_NORESP_NET)
2263f21fb3edSRaghu Vatsavayi 		ndata->reqtype = REQTYPE_RESP_NET;
2264f21fb3edSRaghu Vatsavayi 	else if (ndata->reqtype == REQTYPE_NORESP_NET_SG)
2265f21fb3edSRaghu Vatsavayi 		ndata->reqtype = REQTYPE_RESP_NET_SG;
2266f21fb3edSRaghu Vatsavayi 
2267f21fb3edSRaghu Vatsavayi 	sc->callback = handle_timestamp;
2268f21fb3edSRaghu Vatsavayi 	sc->callback_arg = finfo->skb;
2269f21fb3edSRaghu Vatsavayi 	sc->iq_no = ndata->q_no;
2270f21fb3edSRaghu Vatsavayi 
2271f21fb3edSRaghu Vatsavayi 	if (OCTEON_CN23XX_PF(oct))
2272f21fb3edSRaghu Vatsavayi 		len = (u32)((struct octeon_instr_ih3 *)
2273f21fb3edSRaghu Vatsavayi 			    (&sc->cmd.cmd3.ih3))->dlengsz;
2274f21fb3edSRaghu Vatsavayi 	else
2275f21fb3edSRaghu Vatsavayi 		len = (u32)((struct octeon_instr_ih2 *)
22765b823514SRaghu Vatsavayi 			    (&sc->cmd.cmd2.ih2))->dlengsz;
22775b823514SRaghu Vatsavayi 
22785b823514SRaghu Vatsavayi 	ring_doorbell = !xmit_more;
22795b823514SRaghu Vatsavayi 
22805b823514SRaghu Vatsavayi 	retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd,
22815b823514SRaghu Vatsavayi 				     sc, len, ndata->reqtype);
2282f21fb3edSRaghu Vatsavayi 
2283c859e21aSIntiyaz Basha 	if (retval == IQ_SEND_FAILED) {
22845b823514SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "timestamp data packet failed status: %x\n",
2285f21fb3edSRaghu Vatsavayi 			retval);
22866a885b60SRaghu Vatsavayi 		octeon_free_soft_command(oct, sc);
2287f21fb3edSRaghu Vatsavayi 	} else {
2288ddc173a6SRaghu Vatsavayi 		netif_info(lio, tx_queued, lio->netdev, "Queued timestamp packet\n");
2289f21fb3edSRaghu Vatsavayi 	}
2290f21fb3edSRaghu Vatsavayi 
2291f21fb3edSRaghu Vatsavayi 	return retval;
2292f21fb3edSRaghu Vatsavayi }
2293f21fb3edSRaghu Vatsavayi 
2294f21fb3edSRaghu Vatsavayi /**
2295f21fb3edSRaghu Vatsavayi  * liquidio_xmit - Transmit networks packets to the Octeon interface
2296f21fb3edSRaghu Vatsavayi  * @skb: skbuff struct to be passed to network layer.
2297f21fb3edSRaghu Vatsavayi  * @netdev: pointer to network device
2298f21fb3edSRaghu Vatsavayi  *
2299d0ea5cbdSJesse Brandeburg  * Return: whether the packet was transmitted to the device okay or not
2300d0ea5cbdSJesse Brandeburg  *             (NETDEV_TX_OK or NETDEV_TX_BUSY)
2301d0ea5cbdSJesse Brandeburg  */
liquidio_xmit(struct sk_buff * skb,struct net_device * netdev)2302d0ea5cbdSJesse Brandeburg static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
2303d0ea5cbdSJesse Brandeburg {
2304d0ea5cbdSJesse Brandeburg 	struct lio *lio;
2305f21fb3edSRaghu Vatsavayi 	struct octnet_buf_free_info *finfo;
2306f21fb3edSRaghu Vatsavayi 	union octnic_cmd_setup cmdsetup;
2307ac1172deSYueHaibing 	struct octnic_data_pkt ndata;
2308f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct;
2309f21fb3edSRaghu Vatsavayi 	struct oct_iq_stats *stats;
2310f21fb3edSRaghu Vatsavayi 	struct octeon_instr_irh *irh;
2311f21fb3edSRaghu Vatsavayi 	union tx_info *tx_info;
2312f21fb3edSRaghu Vatsavayi 	int status = 0;
2313f21fb3edSRaghu Vatsavayi 	int q_idx = 0, iq_no = 0;
2314f21fb3edSRaghu Vatsavayi 	int j, xmit_more = 0;
23156a885b60SRaghu Vatsavayi 	u64 dptr = 0;
23166a885b60SRaghu Vatsavayi 	u32 tag = 0;
231726236fa9SRaghu Vatsavayi 
2318f21fb3edSRaghu Vatsavayi 	lio = GET_LIO(netdev);
2319c859e21aSIntiyaz Basha 	oct = lio->oct_dev;
2320fcd2b5e3SRaghu Vatsavayi 
2321f21fb3edSRaghu Vatsavayi 	q_idx = skb_iq(oct, skb);
2322f21fb3edSRaghu Vatsavayi 	tag = q_idx;
2323f21fb3edSRaghu Vatsavayi 	iq_no = lio->linfo.txpciq[q_idx].s.q_no;
2324f21fb3edSRaghu Vatsavayi 
2325f21fb3edSRaghu Vatsavayi 	stats = &oct->instr_queue[iq_no]->stats;
2326c33c9973SIntiyaz Basha 
232726236fa9SRaghu Vatsavayi 	/* Check for all conditions in which the current packet cannot be
232826236fa9SRaghu Vatsavayi 	 * transmitted.
2329f21fb3edSRaghu Vatsavayi 	 */
2330f21fb3edSRaghu Vatsavayi 	if (!(atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING) ||
2331f21fb3edSRaghu Vatsavayi 	    (!lio->linfo.link.s.link_up) ||
2332f21fb3edSRaghu Vatsavayi 	    (skb->len <= 0)) {
2333f21fb3edSRaghu Vatsavayi 		netif_info(lio, tx_err, lio->netdev,
2334f21fb3edSRaghu Vatsavayi 			   "Transmit failed link_status : %d\n",
2335f21fb3edSRaghu Vatsavayi 			   lio->linfo.link.s.link_up);
23360cece6c5SRaghu Vatsavayi 		goto lio_xmit_failed;
2337f21fb3edSRaghu Vatsavayi 	}
2338f21fb3edSRaghu Vatsavayi 
2339f21fb3edSRaghu Vatsavayi 	/* Use space in skb->cb to store info used to unmap and
23400cece6c5SRaghu Vatsavayi 	 * free the buffers.
2341f21fb3edSRaghu Vatsavayi 	 */
2342f21fb3edSRaghu Vatsavayi 	finfo = (struct octnet_buf_free_info *)skb->cb;
2343f21fb3edSRaghu Vatsavayi 	finfo->lio = lio;
2344f21fb3edSRaghu Vatsavayi 	finfo->skb = skb;
2345f21fb3edSRaghu Vatsavayi 	finfo->sc = NULL;
2346f21fb3edSRaghu Vatsavayi 
2347f21fb3edSRaghu Vatsavayi 	/* Prepare the attributes for the data to be passed to OSI. */
2348f21fb3edSRaghu Vatsavayi 	memset(&ndata, 0, sizeof(struct octnic_data_pkt));
2349f21fb3edSRaghu Vatsavayi 
2350f21fb3edSRaghu Vatsavayi 	ndata.buf = (void *)finfo;
2351f21fb3edSRaghu Vatsavayi 
2352f21fb3edSRaghu Vatsavayi 	ndata.q_no = iq_no;
2353f21fb3edSRaghu Vatsavayi 
2354f21fb3edSRaghu Vatsavayi 	if (octnet_iq_is_full(oct, ndata.q_no)) {
2355f21fb3edSRaghu Vatsavayi 		/* defer sending if queue is full */
2356f21fb3edSRaghu Vatsavayi 		netif_info(lio, tx_err, lio->netdev, "Transmit failed iq:%d full\n",
2357f21fb3edSRaghu Vatsavayi 			   ndata.q_no);
2358f21fb3edSRaghu Vatsavayi 		stats->tx_iq_busy++;
2359f21fb3edSRaghu Vatsavayi 		return NETDEV_TX_BUSY;
2360f21fb3edSRaghu Vatsavayi 	}
2361f21fb3edSRaghu Vatsavayi 
2362f21fb3edSRaghu Vatsavayi 	/* pr_info(" XMIT - valid Qs: %d, 1st Q no: %d, cpu:  %d, q_no:%d\n",
2363f21fb3edSRaghu Vatsavayi 	 *	lio->linfo.num_txpciq, lio->txq, cpu, ndata.q_no);
2364f21fb3edSRaghu Vatsavayi 	 */
2365f21fb3edSRaghu Vatsavayi 
23662a2fabafSIntiyaz Basha 	ndata.datasize = skb->len;
2367f21fb3edSRaghu Vatsavayi 
2368f21fb3edSRaghu Vatsavayi 	cmdsetup.u64 = 0;
2369f21fb3edSRaghu Vatsavayi 	cmdsetup.s.iq_no = iq_no;
2370f21fb3edSRaghu Vatsavayi 
2371f21fb3edSRaghu Vatsavayi 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
2372f21fb3edSRaghu Vatsavayi 		if (skb->encapsulation) {
2373f21fb3edSRaghu Vatsavayi 			cmdsetup.s.tnl_csum = 1;
23747275ebfcSRaghu Vatsavayi 			stats->tx_vxlan++;
2375f21fb3edSRaghu Vatsavayi 		} else {
237601fb237aSRaghu Vatsavayi 			cmdsetup.s.transport_csum = 1;
237701fb237aSRaghu Vatsavayi 		}
237801fb237aSRaghu Vatsavayi 	}
237901fb237aSRaghu Vatsavayi 	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
238001fb237aSRaghu Vatsavayi 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
23817275ebfcSRaghu Vatsavayi 		cmdsetup.s.timestamp = 1;
238201fb237aSRaghu Vatsavayi 	}
238301fb237aSRaghu Vatsavayi 
2384f21fb3edSRaghu Vatsavayi 	if (skb_shinfo(skb)->nr_frags == 0) {
2385f21fb3edSRaghu Vatsavayi 		cmdsetup.s.u.datasize = skb->len;
2386f21fb3edSRaghu Vatsavayi 		octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
2387f21fb3edSRaghu Vatsavayi 
2388f21fb3edSRaghu Vatsavayi 		/* Offload checksum calculation for TCP/UDP packets */
2389f21fb3edSRaghu Vatsavayi 		dptr = dma_map_single(&oct->pci_dev->dev,
2390f21fb3edSRaghu Vatsavayi 				      skb->data,
23910cece6c5SRaghu Vatsavayi 				      skb->len,
2392a2c64b67SRaghu Vatsavayi 				      DMA_TO_DEVICE);
2393f21fb3edSRaghu Vatsavayi 		if (dma_mapping_error(&oct->pci_dev->dev, dptr)) {
23946a885b60SRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev, "%s DMA mapping error 1\n",
2395f21fb3edSRaghu Vatsavayi 				__func__);
2396f21fb3edSRaghu Vatsavayi 			stats->tx_dmamap_fail++;
2397f21fb3edSRaghu Vatsavayi 			return NETDEV_TX_BUSY;
23986a885b60SRaghu Vatsavayi 		}
2399f21fb3edSRaghu Vatsavayi 
2400f21fb3edSRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(oct))
2401897ddc24SIntiyaz Basha 			ndata.cmd.cmd3.dptr = dptr;
2402f21fb3edSRaghu Vatsavayi 		else
2403f21fb3edSRaghu Vatsavayi 			ndata.cmd.cmd2.dptr = dptr;
2404f21fb3edSRaghu Vatsavayi 		finfo->dptr = dptr;
24055b823514SRaghu Vatsavayi 		ndata.reqtype = REQTYPE_NORESP_NET;
24065b823514SRaghu Vatsavayi 
24075b823514SRaghu Vatsavayi 	} else {
24086a885b60SRaghu Vatsavayi 		int i, frags;
24096a885b60SRaghu Vatsavayi 		skb_frag_t *frag;
2410f21fb3edSRaghu Vatsavayi 		struct octnic_gather *g;
2411f21fb3edSRaghu Vatsavayi 
2412f21fb3edSRaghu Vatsavayi 		spin_lock(&lio->glist_lock[q_idx]);
2413f21fb3edSRaghu Vatsavayi 		g = (struct octnic_gather *)
2414d7840976SMatthew Wilcox (Oracle) 			lio_list_delete_head(&lio->glist[q_idx]);
2415f21fb3edSRaghu Vatsavayi 		spin_unlock(&lio->glist_lock[q_idx]);
2416f21fb3edSRaghu Vatsavayi 
2417fcd2b5e3SRaghu Vatsavayi 		if (!g) {
2418fcd2b5e3SRaghu Vatsavayi 			netif_info(lio, tx_err, lio->netdev,
241985a0cd81SIntiyaz Basha 				   "Transmit scatter gather: glist null!\n");
2420fcd2b5e3SRaghu Vatsavayi 			goto lio_xmit_failed;
2421f21fb3edSRaghu Vatsavayi 		}
2422f21fb3edSRaghu Vatsavayi 
2423f21fb3edSRaghu Vatsavayi 		cmdsetup.s.gather = 1;
2424f21fb3edSRaghu Vatsavayi 		cmdsetup.s.u.gatherptrs = (skb_shinfo(skb)->nr_frags + 1);
2425f21fb3edSRaghu Vatsavayi 		octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
2426f21fb3edSRaghu Vatsavayi 
2427f21fb3edSRaghu Vatsavayi 		memset(g->sg, 0, g->sg_size);
2428f21fb3edSRaghu Vatsavayi 
2429f21fb3edSRaghu Vatsavayi 		g->sg[0].ptr[0] = dma_map_single(&oct->pci_dev->dev,
24300cece6c5SRaghu Vatsavayi 						 skb->data,
2431f21fb3edSRaghu Vatsavayi 						 (skb->len - skb->data_len),
2432f21fb3edSRaghu Vatsavayi 						 DMA_TO_DEVICE);
2433f21fb3edSRaghu Vatsavayi 		if (dma_mapping_error(&oct->pci_dev->dev, g->sg[0].ptr[0])) {
2434f21fb3edSRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev, "%s DMA mapping error 2\n",
2435f21fb3edSRaghu Vatsavayi 				__func__);
2436f21fb3edSRaghu Vatsavayi 			stats->tx_dmamap_fail++;
2437f21fb3edSRaghu Vatsavayi 			return NETDEV_TX_BUSY;
2438f21fb3edSRaghu Vatsavayi 		}
2439f21fb3edSRaghu Vatsavayi 		add_sg_size(&g->sg[0], (skb->len - skb->data_len), 0);
2440f21fb3edSRaghu Vatsavayi 
2441897ddc24SIntiyaz Basha 		frags = skb_shinfo(skb)->nr_frags;
2442f21fb3edSRaghu Vatsavayi 		i = 1;
2443f21fb3edSRaghu Vatsavayi 		while (frags--) {
2444f21fb3edSRaghu Vatsavayi 			frag = &skb_shinfo(skb)->frags[i - 1];
2445f21fb3edSRaghu Vatsavayi 
2446f21fb3edSRaghu Vatsavayi 			g->sg[(i >> 2)].ptr[(i & 3)] =
2447f21fb3edSRaghu Vatsavayi 				skb_frag_dma_map(&oct->pci_dev->dev,
2448f21fb3edSRaghu Vatsavayi 					         frag, 0, skb_frag_size(frag),
2449f21fb3edSRaghu Vatsavayi 						 DMA_TO_DEVICE);
2450f21fb3edSRaghu Vatsavayi 
2451f21fb3edSRaghu Vatsavayi 			if (dma_mapping_error(&oct->pci_dev->dev,
2452d7840976SMatthew Wilcox (Oracle) 					      g->sg[i >> 2].ptr[i & 3])) {
2453d7840976SMatthew Wilcox (Oracle) 				dma_unmap_single(&oct->pci_dev->dev,
2454f21fb3edSRaghu Vatsavayi 						 g->sg[0].ptr[0],
2455f21fb3edSRaghu Vatsavayi 						 skb->len - skb->data_len,
2456fcd2b5e3SRaghu Vatsavayi 						 DMA_TO_DEVICE);
2457fcd2b5e3SRaghu Vatsavayi 				for (j = 1; j < i; j++) {
2458fcd2b5e3SRaghu Vatsavayi 					frag = &skb_shinfo(skb)->frags[j - 1];
2459fcd2b5e3SRaghu Vatsavayi 					dma_unmap_page(&oct->pci_dev->dev,
2460fcd2b5e3SRaghu Vatsavayi 						       g->sg[j >> 2].ptr[j & 3],
2461fcd2b5e3SRaghu Vatsavayi 						       skb_frag_size(frag),
2462fcd2b5e3SRaghu Vatsavayi 						       DMA_TO_DEVICE);
2463fcd2b5e3SRaghu Vatsavayi 				}
2464fcd2b5e3SRaghu Vatsavayi 				dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n",
2465fcd2b5e3SRaghu Vatsavayi 					__func__);
2466d7840976SMatthew Wilcox (Oracle) 				return NETDEV_TX_BUSY;
2467fcd2b5e3SRaghu Vatsavayi 			}
2468fcd2b5e3SRaghu Vatsavayi 
2469fcd2b5e3SRaghu Vatsavayi 			add_sg_size(&g->sg[(i >> 2)], skb_frag_size(frag),
2470fcd2b5e3SRaghu Vatsavayi 				    (i & 3));
2471fcd2b5e3SRaghu Vatsavayi 			i++;
2472fcd2b5e3SRaghu Vatsavayi 		}
2473fcd2b5e3SRaghu Vatsavayi 
2474d7840976SMatthew Wilcox (Oracle) 		dptr = g->sg_dma_ptr;
2475d7840976SMatthew Wilcox (Oracle) 
2476f21fb3edSRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(oct))
2477f21fb3edSRaghu Vatsavayi 			ndata.cmd.cmd3.dptr = dptr;
2478f21fb3edSRaghu Vatsavayi 		else
2479fcd2b5e3SRaghu Vatsavayi 			ndata.cmd.cmd2.dptr = dptr;
2480f21fb3edSRaghu Vatsavayi 		finfo->dptr = dptr;
24815b823514SRaghu Vatsavayi 		finfo->g = g;
24825b823514SRaghu Vatsavayi 
24835b823514SRaghu Vatsavayi 		ndata.reqtype = REQTYPE_NORESP_NET_SG;
24846a885b60SRaghu Vatsavayi 	}
24856a885b60SRaghu Vatsavayi 
2486f21fb3edSRaghu Vatsavayi 	if (OCTEON_CN23XX_PF(oct)) {
2487f21fb3edSRaghu Vatsavayi 		irh = (struct octeon_instr_irh *)&ndata.cmd.cmd3.irh;
2488f21fb3edSRaghu Vatsavayi 		tx_info = (union tx_info *)&ndata.cmd.cmd3.ossp[0];
2489f21fb3edSRaghu Vatsavayi 	} else {
2490f21fb3edSRaghu Vatsavayi 		irh = (struct octeon_instr_irh *)&ndata.cmd.cmd2.irh;
24915b823514SRaghu Vatsavayi 		tx_info = (union tx_info *)&ndata.cmd.cmd2.ossp[0];
24925b823514SRaghu Vatsavayi 	}
24935b823514SRaghu Vatsavayi 
24945b823514SRaghu Vatsavayi 	if (skb_shinfo(skb)->gso_size) {
24956a885b60SRaghu Vatsavayi 		tx_info->s.gso_size = skb_shinfo(skb)->gso_size;
24966a885b60SRaghu Vatsavayi 		tx_info->s.gso_segs = skb_shinfo(skb)->gso_segs;
24975b823514SRaghu Vatsavayi 		stats->tx_gso++;
2498f21fb3edSRaghu Vatsavayi 	}
24996a885b60SRaghu Vatsavayi 
2500f21fb3edSRaghu Vatsavayi 	/* HW insert VLAN tag */
2501f21fb3edSRaghu Vatsavayi 	if (skb_vlan_tag_present(skb)) {
25021f164717SRaghu Vatsavayi 		irh->priority = skb_vlan_tag_get(skb) >> 13;
2503f21fb3edSRaghu Vatsavayi 		irh->vlan = skb_vlan_tag_get(skb) & 0xfff;
25041f164717SRaghu Vatsavayi 	}
25050da0b77cSRaghu Vatsavayi 
25060da0b77cSRaghu Vatsavayi 	xmit_more = netdev_xmit_more();
25070da0b77cSRaghu Vatsavayi 
25080da0b77cSRaghu Vatsavayi 	if (unlikely(cmdsetup.s.timestamp))
25090da0b77cSRaghu Vatsavayi 		status = send_nic_timestamp_pkt(oct, &ndata, finfo, xmit_more);
2510f21fb3edSRaghu Vatsavayi 	else
25116b16f9eeSFlorian Westphal 		status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more);
2512c859e21aSIntiyaz Basha 	if (status == IQ_SEND_FAILED)
2513f21fb3edSRaghu Vatsavayi 		goto lio_xmit_failed;
2514c859e21aSIntiyaz Basha 
2515f21fb3edSRaghu Vatsavayi 	netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n");
2516c859e21aSIntiyaz Basha 
2517f21fb3edSRaghu Vatsavayi 	if (status == IQ_SEND_STOP)
2518f21fb3edSRaghu Vatsavayi 		netif_stop_subqueue(netdev, q_idx);
2519f21fb3edSRaghu Vatsavayi 
2520f21fb3edSRaghu Vatsavayi 	netif_trans_update(netdev);
2521f21fb3edSRaghu Vatsavayi 
2522f21fb3edSRaghu Vatsavayi 	if (tx_info->s.gso_segs)
252378a202f0SIntiyaz Basha 		stats->tx_done += tx_info->s.gso_segs;
2524f21fb3edSRaghu Vatsavayi 	else
2525860e9538SFlorian Westphal 		stats->tx_done++;
2526f21fb3edSRaghu Vatsavayi 	stats->tx_tot_bytes += ndata.datasize;
252780c8eae6SSatanand Burla 
252880c8eae6SSatanand Burla 	return NETDEV_TX_OK;
25291f164717SRaghu Vatsavayi 
2530f21fb3edSRaghu Vatsavayi lio_xmit_failed:
253180c8eae6SSatanand Burla 	stats->tx_dropped++;
2532f21fb3edSRaghu Vatsavayi 	netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n",
2533f21fb3edSRaghu Vatsavayi 		   iq_no, stats->tx_dropped);
2534f21fb3edSRaghu Vatsavayi 	if (dptr)
2535f21fb3edSRaghu Vatsavayi 		dma_unmap_single(&oct->pci_dev->dev, dptr,
2536f21fb3edSRaghu Vatsavayi 				 ndata.datasize, DMA_TO_DEVICE);
2537f21fb3edSRaghu Vatsavayi 
2538f21fb3edSRaghu Vatsavayi 	octeon_ring_doorbell_locked(oct, iq_no);
25396a885b60SRaghu Vatsavayi 
25406a885b60SRaghu Vatsavayi 	tx_buffer_free(skb);
2541f21fb3edSRaghu Vatsavayi 	return NETDEV_TX_OK;
2542c859e21aSIntiyaz Basha }
2543c859e21aSIntiyaz Basha 
2544c859e21aSIntiyaz Basha /**
2545cabeb13bSRaghu Vatsavayi  * liquidio_tx_timeout - Network device Tx timeout
2546f21fb3edSRaghu Vatsavayi  * @netdev:    pointer to network device
2547f21fb3edSRaghu Vatsavayi  * @txqueue: index of the hung transmit queue
2548f21fb3edSRaghu Vatsavayi  */
liquidio_tx_timeout(struct net_device * netdev,unsigned int txqueue)2549d0ea5cbdSJesse Brandeburg static void liquidio_tx_timeout(struct net_device *netdev, unsigned int txqueue)
2550d0ea5cbdSJesse Brandeburg {
2551d0ea5cbdSJesse Brandeburg 	struct lio *lio;
2552d0ea5cbdSJesse Brandeburg 
2553f21fb3edSRaghu Vatsavayi 	lio = GET_LIO(netdev);
25540290bd29SMichael S. Tsirkin 
2555f21fb3edSRaghu Vatsavayi 	netif_info(lio, tx_err, lio->netdev,
2556f21fb3edSRaghu Vatsavayi 		   "Transmit timeout tx_dropped:%ld, waking up queues now!!\n",
2557f21fb3edSRaghu Vatsavayi 		   netdev->stats.tx_dropped);
2558f21fb3edSRaghu Vatsavayi 	netif_trans_update(netdev);
2559f21fb3edSRaghu Vatsavayi 	wake_txqs(netdev);
2560f21fb3edSRaghu Vatsavayi }
2561f21fb3edSRaghu Vatsavayi 
liquidio_vlan_rx_add_vid(struct net_device * netdev,__be16 proto,u16 vid)2562f21fb3edSRaghu Vatsavayi static int liquidio_vlan_rx_add_vid(struct net_device *netdev,
2563860e9538SFlorian Westphal 				    __be16 proto __attribute__((unused)),
2564a96d8ad3SIntiyaz Basha 				    u16 vid)
2565f21fb3edSRaghu Vatsavayi {
2566f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
256763245f25SRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
256863245f25SRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
256963245f25SRaghu Vatsavayi 	int ret = 0;
257063245f25SRaghu Vatsavayi 
257163245f25SRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
257263245f25SRaghu Vatsavayi 
257363245f25SRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
257463245f25SRaghu Vatsavayi 	nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
257563245f25SRaghu Vatsavayi 	nctrl.ncmd.s.param1 = vid;
257663245f25SRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
257763245f25SRaghu Vatsavayi 	nctrl.netpndev = (u64)netdev;
257863245f25SRaghu Vatsavayi 	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
257963245f25SRaghu Vatsavayi 
258063245f25SRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
258163245f25SRaghu Vatsavayi 	if (ret) {
258263245f25SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
258363245f25SRaghu Vatsavayi 			ret);
258463245f25SRaghu Vatsavayi 		if (ret > 0)
258563245f25SRaghu Vatsavayi 			ret = -EIO;
2586edd572d7SFelix Manlunas 	}
258763245f25SRaghu Vatsavayi 
258863245f25SRaghu Vatsavayi 	return ret;
2589edd572d7SFelix Manlunas }
2590edd572d7SFelix Manlunas 
liquidio_vlan_rx_kill_vid(struct net_device * netdev,__be16 proto,u16 vid)259163245f25SRaghu Vatsavayi static int liquidio_vlan_rx_kill_vid(struct net_device *netdev,
259263245f25SRaghu Vatsavayi 				     __be16 proto __attribute__((unused)),
259363245f25SRaghu Vatsavayi 				     u16 vid)
259463245f25SRaghu Vatsavayi {
259563245f25SRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
259663245f25SRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
259763245f25SRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
259863245f25SRaghu Vatsavayi 	int ret = 0;
259963245f25SRaghu Vatsavayi 
260063245f25SRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
260163245f25SRaghu Vatsavayi 
260263245f25SRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
260363245f25SRaghu Vatsavayi 	nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
260463245f25SRaghu Vatsavayi 	nctrl.ncmd.s.param1 = vid;
260563245f25SRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
260663245f25SRaghu Vatsavayi 	nctrl.netpndev = (u64)netdev;
260763245f25SRaghu Vatsavayi 	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
260863245f25SRaghu Vatsavayi 
260963245f25SRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
261063245f25SRaghu Vatsavayi 	if (ret) {
261163245f25SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Del VLAN filter failed in core (ret: 0x%x)\n",
261263245f25SRaghu Vatsavayi 			ret);
261363245f25SRaghu Vatsavayi 		if (ret > 0)
261463245f25SRaghu Vatsavayi 			ret = -EIO;
2615edd572d7SFelix Manlunas 	}
2616fcaccc82SRick Farrington 	return ret;
261763245f25SRaghu Vatsavayi }
2618edd572d7SFelix Manlunas 
2619edd572d7SFelix Manlunas /**
262063245f25SRaghu Vatsavayi  * liquidio_set_rxcsum_command - Sending command to enable/disable RX checksum offload
262163245f25SRaghu Vatsavayi  * @netdev:                pointer to network device
262263245f25SRaghu Vatsavayi  * @command:               OCTNET_CMD_TNL_RX_CSUM_CTL
262363245f25SRaghu Vatsavayi  * @rx_cmd:                OCTNET_CMD_RXCSUM_ENABLE/OCTNET_CMD_RXCSUM_DISABLE
2624d0ea5cbdSJesse Brandeburg  * Returns:                SUCCESS or FAILURE
2625d0ea5cbdSJesse Brandeburg  */
liquidio_set_rxcsum_command(struct net_device * netdev,int command,u8 rx_cmd)2626d0ea5cbdSJesse Brandeburg static int liquidio_set_rxcsum_command(struct net_device *netdev, int command,
2627d0ea5cbdSJesse Brandeburg 				       u8 rx_cmd)
2628d0ea5cbdSJesse Brandeburg {
2629d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
263001fb237aSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
2631c41419b0SNicholas Mc Guire 	struct octnic_ctrl_pkt nctrl;
263201fb237aSRaghu Vatsavayi 	int ret = 0;
263301fb237aSRaghu Vatsavayi 
263401fb237aSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
263501fb237aSRaghu Vatsavayi 
263601fb237aSRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
263701fb237aSRaghu Vatsavayi 	nctrl.ncmd.s.cmd = command;
263801fb237aSRaghu Vatsavayi 	nctrl.ncmd.s.param1 = rx_cmd;
26390c264588SFelix Manlunas 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
26400c264588SFelix Manlunas 	nctrl.netpndev = (u64)netdev;
264101fb237aSRaghu Vatsavayi 	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
264201fb237aSRaghu Vatsavayi 
264301fb237aSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
264401fb237aSRaghu Vatsavayi 	if (ret) {
264501fb237aSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev,
264601fb237aSRaghu Vatsavayi 			"DEVFLAGS RXCSUM change failed in core(ret:0x%x)\n",
264701fb237aSRaghu Vatsavayi 			ret);
264801fb237aSRaghu Vatsavayi 		if (ret > 0)
2649edd572d7SFelix Manlunas 			ret = -EIO;
265001fb237aSRaghu Vatsavayi 	}
265101fb237aSRaghu Vatsavayi 	return ret;
265201fb237aSRaghu Vatsavayi }
2653edd572d7SFelix Manlunas 
2654edd572d7SFelix Manlunas /**
265501fb237aSRaghu Vatsavayi  * liquidio_vxlan_port_command - Sending command to add/delete VxLAN UDP port to firmware
265601fb237aSRaghu Vatsavayi  * @netdev:                pointer to network device
265701fb237aSRaghu Vatsavayi  * @command:               OCTNET_CMD_VXLAN_PORT_CONFIG
265801fb237aSRaghu Vatsavayi  * @vxlan_port:            VxLAN port to be added or deleted
2659d0ea5cbdSJesse Brandeburg  * @vxlan_cmd_bit:         OCTNET_CMD_VXLAN_PORT_ADD,
2660d0ea5cbdSJesse Brandeburg  *                              OCTNET_CMD_VXLAN_PORT_DEL
2661d0ea5cbdSJesse Brandeburg  * Return:                     SUCCESS or FAILURE
2662d0ea5cbdSJesse Brandeburg  */
liquidio_vxlan_port_command(struct net_device * netdev,int command,u16 vxlan_port,u8 vxlan_cmd_bit)2663d0ea5cbdSJesse Brandeburg static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
2664d0ea5cbdSJesse Brandeburg 				       u16 vxlan_port, u8 vxlan_cmd_bit)
266501fb237aSRaghu Vatsavayi {
2666d0ea5cbdSJesse Brandeburg 	struct lio *lio = GET_LIO(netdev);
266701fb237aSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
266801fb237aSRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
266901fb237aSRaghu Vatsavayi 	int ret = 0;
267001fb237aSRaghu Vatsavayi 
267101fb237aSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
267201fb237aSRaghu Vatsavayi 
267301fb237aSRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
267401fb237aSRaghu Vatsavayi 	nctrl.ncmd.s.cmd = command;
267501fb237aSRaghu Vatsavayi 	nctrl.ncmd.s.more = vxlan_cmd_bit;
26760c264588SFelix Manlunas 	nctrl.ncmd.s.param1 = vxlan_port;
26770c264588SFelix Manlunas 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
267801fb237aSRaghu Vatsavayi 	nctrl.netpndev = (u64)netdev;
267901fb237aSRaghu Vatsavayi 	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
268001fb237aSRaghu Vatsavayi 
268101fb237aSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
268201fb237aSRaghu Vatsavayi 	if (ret) {
268301fb237aSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev,
268401fb237aSRaghu Vatsavayi 			"VxLAN port add/delete failed in core (ret:0x%x)\n",
268501fb237aSRaghu Vatsavayi 			ret);
268601fb237aSRaghu Vatsavayi 		if (ret > 0)
2687edd572d7SFelix Manlunas 			ret = -EIO;
268801fb237aSRaghu Vatsavayi 	}
268901fb237aSRaghu Vatsavayi 	return ret;
269001fb237aSRaghu Vatsavayi }
2691edd572d7SFelix Manlunas 
liquidio_udp_tunnel_set_port(struct net_device * netdev,unsigned int table,unsigned int entry,struct udp_tunnel_info * ti)2692edd572d7SFelix Manlunas static int liquidio_udp_tunnel_set_port(struct net_device *netdev,
269301fb237aSRaghu Vatsavayi 					unsigned int table, unsigned int entry,
269401fb237aSRaghu Vatsavayi 					struct udp_tunnel_info *ti)
269501fb237aSRaghu Vatsavayi {
269601fb237aSRaghu Vatsavayi 	return liquidio_vxlan_port_command(netdev,
26973fcd2ba1SJakub Kicinski 					   OCTNET_CMD_VXLAN_PORT_CONFIG,
26983fcd2ba1SJakub Kicinski 					   htons(ti->port),
26993fcd2ba1SJakub Kicinski 					   OCTNET_CMD_VXLAN_PORT_ADD);
27003fcd2ba1SJakub Kicinski }
27013fcd2ba1SJakub Kicinski 
liquidio_udp_tunnel_unset_port(struct net_device * netdev,unsigned int table,unsigned int entry,struct udp_tunnel_info * ti)27023fcd2ba1SJakub Kicinski static int liquidio_udp_tunnel_unset_port(struct net_device *netdev,
27033fcd2ba1SJakub Kicinski 					  unsigned int table,
27043fcd2ba1SJakub Kicinski 					  unsigned int entry,
27053fcd2ba1SJakub Kicinski 					  struct udp_tunnel_info *ti)
27063fcd2ba1SJakub Kicinski {
27073fcd2ba1SJakub Kicinski 	return liquidio_vxlan_port_command(netdev,
27083fcd2ba1SJakub Kicinski 					   OCTNET_CMD_VXLAN_PORT_CONFIG,
27093fcd2ba1SJakub Kicinski 					   htons(ti->port),
27103fcd2ba1SJakub Kicinski 					   OCTNET_CMD_VXLAN_PORT_DEL);
27113fcd2ba1SJakub Kicinski }
27123fcd2ba1SJakub Kicinski 
27133fcd2ba1SJakub Kicinski static const struct udp_tunnel_nic_info liquidio_udp_tunnels = {
27143fcd2ba1SJakub Kicinski 	.set_port	= liquidio_udp_tunnel_set_port,
27153fcd2ba1SJakub Kicinski 	.unset_port	= liquidio_udp_tunnel_unset_port,
27163fcd2ba1SJakub Kicinski 	.tables		= {
27173fcd2ba1SJakub Kicinski 		{ .n_entries = 1024, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
27183fcd2ba1SJakub Kicinski 	},
27193fcd2ba1SJakub Kicinski };
27203fcd2ba1SJakub Kicinski 
27213fcd2ba1SJakub Kicinski /**
27223fcd2ba1SJakub Kicinski  * liquidio_fix_features - Net device fix features
27233fcd2ba1SJakub Kicinski  * @netdev:  pointer to network device
27243fcd2ba1SJakub Kicinski  * @request: features requested
27253fcd2ba1SJakub Kicinski  * Return: updated features list
2726d0ea5cbdSJesse Brandeburg  */
liquidio_fix_features(struct net_device * netdev,netdev_features_t request)2727d0ea5cbdSJesse Brandeburg static netdev_features_t liquidio_fix_features(struct net_device *netdev,
2728d0ea5cbdSJesse Brandeburg 					       netdev_features_t request)
2729d0ea5cbdSJesse Brandeburg {
2730d0ea5cbdSJesse Brandeburg 	struct lio *lio = netdev_priv(netdev);
2731f21fb3edSRaghu Vatsavayi 
2732f21fb3edSRaghu Vatsavayi 	if ((request & NETIF_F_RXCSUM) &&
2733f21fb3edSRaghu Vatsavayi 	    !(lio->dev_capability & NETIF_F_RXCSUM))
2734f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_RXCSUM;
2735f21fb3edSRaghu Vatsavayi 
2736f21fb3edSRaghu Vatsavayi 	if ((request & NETIF_F_HW_CSUM) &&
2737f21fb3edSRaghu Vatsavayi 	    !(lio->dev_capability & NETIF_F_HW_CSUM))
2738f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_HW_CSUM;
2739f21fb3edSRaghu Vatsavayi 
2740f21fb3edSRaghu Vatsavayi 	if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
2741f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_TSO;
2742f21fb3edSRaghu Vatsavayi 
2743f21fb3edSRaghu Vatsavayi 	if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
2744f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_TSO6;
2745f21fb3edSRaghu Vatsavayi 
2746f21fb3edSRaghu Vatsavayi 	if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
2747f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_LRO;
2748f21fb3edSRaghu Vatsavayi 
2749f21fb3edSRaghu Vatsavayi 	/*Disable LRO if RXCSUM is off */
2750f21fb3edSRaghu Vatsavayi 	if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
2751f21fb3edSRaghu Vatsavayi 	    (lio->dev_capability & NETIF_F_LRO))
2752f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_LRO;
2753f21fb3edSRaghu Vatsavayi 
2754f21fb3edSRaghu Vatsavayi 	if ((request & NETIF_F_HW_VLAN_CTAG_FILTER) &&
2755f21fb3edSRaghu Vatsavayi 	    !(lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER))
2756f21fb3edSRaghu Vatsavayi 		request &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
2757f21fb3edSRaghu Vatsavayi 
2758f21fb3edSRaghu Vatsavayi 	return request;
2759836d57e5SPrasad Kanneganti }
2760836d57e5SPrasad Kanneganti 
2761836d57e5SPrasad Kanneganti /**
2762836d57e5SPrasad Kanneganti  * liquidio_set_features - Net device set features
2763f21fb3edSRaghu Vatsavayi  * @netdev:  pointer to network device
2764f21fb3edSRaghu Vatsavayi  * @features: features to enable/disable
2765f21fb3edSRaghu Vatsavayi  */
liquidio_set_features(struct net_device * netdev,netdev_features_t features)2766d0ea5cbdSJesse Brandeburg static int liquidio_set_features(struct net_device *netdev,
2767d0ea5cbdSJesse Brandeburg 				 netdev_features_t features)
2768d0ea5cbdSJesse Brandeburg {
2769d0ea5cbdSJesse Brandeburg 	struct lio *lio = netdev_priv(netdev);
2770f21fb3edSRaghu Vatsavayi 
2771f21fb3edSRaghu Vatsavayi 	if ((features & NETIF_F_LRO) &&
2772f21fb3edSRaghu Vatsavayi 	    (lio->dev_capability & NETIF_F_LRO) &&
2773f21fb3edSRaghu Vatsavayi 	    !(netdev->features & NETIF_F_LRO))
2774f21fb3edSRaghu Vatsavayi 		liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
2775f21fb3edSRaghu Vatsavayi 				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
2776836d57e5SPrasad Kanneganti 	else if (!(features & NETIF_F_LRO) &&
2777836d57e5SPrasad Kanneganti 		 (lio->dev_capability & NETIF_F_LRO) &&
2778836d57e5SPrasad Kanneganti 		 (netdev->features & NETIF_F_LRO))
27790cece6c5SRaghu Vatsavayi 		liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE,
27800cece6c5SRaghu Vatsavayi 				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
2781f21fb3edSRaghu Vatsavayi 
2782836d57e5SPrasad Kanneganti 	/* Sending command to firmware to enable/disable RX checksum
2783836d57e5SPrasad Kanneganti 	 * offload settings using ethtool
27840cece6c5SRaghu Vatsavayi 	 */
27850cece6c5SRaghu Vatsavayi 	if (!(netdev->features & NETIF_F_RXCSUM) &&
2786f21fb3edSRaghu Vatsavayi 	    (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
278701fb237aSRaghu Vatsavayi 	    (features & NETIF_F_RXCSUM))
278801fb237aSRaghu Vatsavayi 		liquidio_set_rxcsum_command(netdev,
278901fb237aSRaghu Vatsavayi 					    OCTNET_CMD_TNL_RX_CSUM_CTL,
279001fb237aSRaghu Vatsavayi 					    OCTNET_CMD_RXCSUM_ENABLE);
279101fb237aSRaghu Vatsavayi 	else if ((netdev->features & NETIF_F_RXCSUM) &&
279201fb237aSRaghu Vatsavayi 		 (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
279301fb237aSRaghu Vatsavayi 		 !(features & NETIF_F_RXCSUM))
279401fb237aSRaghu Vatsavayi 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
279501fb237aSRaghu Vatsavayi 					    OCTNET_CMD_RXCSUM_DISABLE);
279601fb237aSRaghu Vatsavayi 
279701fb237aSRaghu Vatsavayi 	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
279801fb237aSRaghu Vatsavayi 	    (lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER) &&
279901fb237aSRaghu Vatsavayi 	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
280001fb237aSRaghu Vatsavayi 		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL,
280101fb237aSRaghu Vatsavayi 				     OCTNET_CMD_VLAN_FILTER_ENABLE);
2802836d57e5SPrasad Kanneganti 	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
2803836d57e5SPrasad Kanneganti 		 (lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER) &&
2804836d57e5SPrasad Kanneganti 		 (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
2805836d57e5SPrasad Kanneganti 		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL,
2806836d57e5SPrasad Kanneganti 				     OCTNET_CMD_VLAN_FILTER_DISABLE);
2807836d57e5SPrasad Kanneganti 
2808836d57e5SPrasad Kanneganti 	return 0;
2809836d57e5SPrasad Kanneganti }
2810836d57e5SPrasad Kanneganti 
__liquidio_set_vf_mac(struct net_device * netdev,int vfidx,u8 * mac,bool is_admin_assigned)2811836d57e5SPrasad Kanneganti static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,
2812836d57e5SPrasad Kanneganti 				 u8 *mac, bool is_admin_assigned)
2813f21fb3edSRaghu Vatsavayi {
2814f21fb3edSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
2815f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
281686dea55bSRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
281786dea55bSRaghu Vatsavayi 	int ret = 0;
281886dea55bSRaghu Vatsavayi 
281986dea55bSRaghu Vatsavayi 	if (!is_valid_ether_addr(mac))
282086dea55bSRaghu Vatsavayi 		return -EINVAL;
282186dea55bSRaghu Vatsavayi 
2822edd572d7SFelix Manlunas 	if (vfidx < 0 || vfidx >= oct->sriov_info.max_vfs)
282386dea55bSRaghu Vatsavayi 		return -EINVAL;
282486dea55bSRaghu Vatsavayi 
282586dea55bSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
282686dea55bSRaghu Vatsavayi 
282786dea55bSRaghu Vatsavayi 	nctrl.ncmd.u64 = 0;
282886dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
282986dea55bSRaghu Vatsavayi 	/* vfidx is 0 based, but vf_num (param1) is 1 based */
283086dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.param1 = vfidx + 1;
283186dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.more = 1;
283286dea55bSRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
283386dea55bSRaghu Vatsavayi 	nctrl.netpndev = (u64)netdev;
283486dea55bSRaghu Vatsavayi 	if (is_admin_assigned) {
283586dea55bSRaghu Vatsavayi 		nctrl.ncmd.s.param2 = true;
283686dea55bSRaghu Vatsavayi 		nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
283786dea55bSRaghu Vatsavayi 	}
28389549c6c8SRick Farrington 
2839edd572d7SFelix Manlunas 	nctrl.udd[0] = 0;
2840edd572d7SFelix Manlunas 	/* The MAC Address is presented in network byte order. */
28419549c6c8SRick Farrington 	ether_addr_copy((u8 *)&nctrl.udd[0] + 2, mac);
2842edd572d7SFelix Manlunas 
284386dea55bSRaghu Vatsavayi 	oct->sriov_info.vf_macaddr[vfidx] = nctrl.udd[0];
284486dea55bSRaghu Vatsavayi 
284586dea55bSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(oct, &nctrl);
284686dea55bSRaghu Vatsavayi 	if (ret > 0)
284786dea55bSRaghu Vatsavayi 		ret = -EIO;
284886dea55bSRaghu Vatsavayi 
284986dea55bSRaghu Vatsavayi 	return ret;
2850edd572d7SFelix Manlunas }
2851edd572d7SFelix Manlunas 
liquidio_set_vf_mac(struct net_device * netdev,int vfidx,u8 * mac)2852edd572d7SFelix Manlunas static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac)
285386dea55bSRaghu Vatsavayi {
2854edd572d7SFelix Manlunas 	struct lio *lio = GET_LIO(netdev);
285586dea55bSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
285686dea55bSRaghu Vatsavayi 	int retval;
285786dea55bSRaghu Vatsavayi 
285886dea55bSRaghu Vatsavayi 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
285986dea55bSRaghu Vatsavayi 		return -EINVAL;
286086dea55bSRaghu Vatsavayi 
286186dea55bSRaghu Vatsavayi 	retval = __liquidio_set_vf_mac(netdev, vfidx, mac, true);
286286dea55bSRaghu Vatsavayi 	if (!retval)
28630d9a5997SFelix Manlunas 		cn23xx_tell_vf_its_macaddr_changed(oct, vfidx, mac);
28640d9a5997SFelix Manlunas 
28650d9a5997SFelix Manlunas 	return retval;
286686dea55bSRaghu Vatsavayi }
286786dea55bSRaghu Vatsavayi 
liquidio_set_vf_spoofchk(struct net_device * netdev,int vfidx,bool enable)286886dea55bSRaghu Vatsavayi static int liquidio_set_vf_spoofchk(struct net_device *netdev, int vfidx,
286986dea55bSRaghu Vatsavayi 				    bool enable)
287086dea55bSRaghu Vatsavayi {
287186dea55bSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
287286dea55bSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
287348875222SWeilin Chang 	struct octnic_ctrl_pkt nctrl;
287448875222SWeilin Chang 	int retval;
287548875222SWeilin Chang 
287648875222SWeilin Chang 	if (!(oct->fw_info.app_cap_flags & LIQUIDIO_SPOOFCHK_CAP)) {
287748875222SWeilin Chang 		netif_info(lio, drv, lio->netdev,
287848875222SWeilin Chang 			   "firmware does not support spoofchk\n");
287948875222SWeilin Chang 		return -EOPNOTSUPP;
288048875222SWeilin Chang 	}
288148875222SWeilin Chang 
288248875222SWeilin Chang 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) {
288348875222SWeilin Chang 		netif_info(lio, drv, lio->netdev, "Invalid vfidx %d\n", vfidx);
288448875222SWeilin Chang 		return -EINVAL;
288548875222SWeilin Chang 	}
288648875222SWeilin Chang 
288748875222SWeilin Chang 	if (enable) {
288848875222SWeilin Chang 		if (oct->sriov_info.vf_spoofchk[vfidx])
288948875222SWeilin Chang 			return 0;
289048875222SWeilin Chang 	} else {
289148875222SWeilin Chang 		/* Clear */
289248875222SWeilin Chang 		if (!oct->sriov_info.vf_spoofchk[vfidx])
289348875222SWeilin Chang 			return 0;
289448875222SWeilin Chang 	}
289548875222SWeilin Chang 
289648875222SWeilin Chang 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
289748875222SWeilin Chang 	nctrl.ncmd.s.cmdgroup = OCTNET_CMD_GROUP1;
289848875222SWeilin Chang 	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_VF_SPOOFCHK;
289948875222SWeilin Chang 	nctrl.ncmd.s.param1 =
290048875222SWeilin Chang 		vfidx + 1; /* vfidx is 0 based,
290148875222SWeilin Chang 			    * but vf_num (param1) is 1 based
290248875222SWeilin Chang 			    */
290348875222SWeilin Chang 	nctrl.ncmd.s.param2 = enable;
290448875222SWeilin Chang 	nctrl.ncmd.s.more = 0;
290548875222SWeilin Chang 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
290648875222SWeilin Chang 	nctrl.cb_fn = NULL;
290748875222SWeilin Chang 
290848875222SWeilin Chang 	retval = octnet_send_nic_ctrl_pkt(oct, &nctrl);
290948875222SWeilin Chang 
291048875222SWeilin Chang 	if (retval) {
2911bf9d787bSYueHaibing 		netif_info(lio, drv, lio->netdev,
291248875222SWeilin Chang 			   "Failed to set VF %d spoofchk %s\n", vfidx,
291348875222SWeilin Chang 			enable ? "on" : "off");
291448875222SWeilin Chang 		return -1;
291548875222SWeilin Chang 	}
291648875222SWeilin Chang 
291748875222SWeilin Chang 	oct->sriov_info.vf_spoofchk[vfidx] = enable;
291848875222SWeilin Chang 	netif_info(lio, drv, lio->netdev, "VF %u spoofchk is %s\n", vfidx,
291948875222SWeilin Chang 		   enable ? "on" : "off");
292048875222SWeilin Chang 
292148875222SWeilin Chang 	return 0;
292248875222SWeilin Chang }
292348875222SWeilin Chang 
liquidio_set_vf_vlan(struct net_device * netdev,int vfidx,u16 vlan,u8 qos,__be16 vlan_proto)292448875222SWeilin Chang static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx,
292548875222SWeilin Chang 				u16 vlan, u8 qos, __be16 vlan_proto)
292648875222SWeilin Chang {
292748875222SWeilin Chang 	struct lio *lio = GET_LIO(netdev);
292848875222SWeilin Chang 	struct octeon_device *oct = lio->oct_dev;
292986dea55bSRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
293086dea55bSRaghu Vatsavayi 	u16 vlantci;
293186dea55bSRaghu Vatsavayi 	int ret = 0;
293286dea55bSRaghu Vatsavayi 
293386dea55bSRaghu Vatsavayi 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
293486dea55bSRaghu Vatsavayi 		return -EINVAL;
293586dea55bSRaghu Vatsavayi 
2936edd572d7SFelix Manlunas 	if (vlan_proto != htons(ETH_P_8021Q))
293786dea55bSRaghu Vatsavayi 		return -EPROTONOSUPPORT;
293886dea55bSRaghu Vatsavayi 
293986dea55bSRaghu Vatsavayi 	if (vlan >= VLAN_N_VID || qos > 7)
294086dea55bSRaghu Vatsavayi 		return -EINVAL;
294186dea55bSRaghu Vatsavayi 
294286dea55bSRaghu Vatsavayi 	if (vlan)
294386dea55bSRaghu Vatsavayi 		vlantci = vlan | (u16)qos << VLAN_PRIO_SHIFT;
294486dea55bSRaghu Vatsavayi 	else
294586dea55bSRaghu Vatsavayi 		vlantci = 0;
294686dea55bSRaghu Vatsavayi 
294786dea55bSRaghu Vatsavayi 	if (oct->sriov_info.vf_vlantci[vfidx] == vlantci)
294886dea55bSRaghu Vatsavayi 		return 0;
294986dea55bSRaghu Vatsavayi 
295086dea55bSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
295186dea55bSRaghu Vatsavayi 
295286dea55bSRaghu Vatsavayi 	if (vlan)
295386dea55bSRaghu Vatsavayi 		nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
295486dea55bSRaghu Vatsavayi 	else
295586dea55bSRaghu Vatsavayi 		nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
295686dea55bSRaghu Vatsavayi 
295786dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.param1 = vlantci;
295886dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.param2 =
295986dea55bSRaghu Vatsavayi 	    vfidx + 1; /* vfidx is 0 based, but vf_num (param2) is 1 based */
296086dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.more = 0;
296186dea55bSRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
296286dea55bSRaghu Vatsavayi 	nctrl.cb_fn = NULL;
296386dea55bSRaghu Vatsavayi 
296486dea55bSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(oct, &nctrl);
296586dea55bSRaghu Vatsavayi 	if (ret) {
296686dea55bSRaghu Vatsavayi 		if (ret > 0)
2967bf20a5c1SYueHaibing 			ret = -EIO;
296886dea55bSRaghu Vatsavayi 		return ret;
2969edd572d7SFelix Manlunas 	}
2970edd572d7SFelix Manlunas 
2971edd572d7SFelix Manlunas 	oct->sriov_info.vf_vlantci[vfidx] = vlantci;
2972edd572d7SFelix Manlunas 
2973edd572d7SFelix Manlunas 	return ret;
2974edd572d7SFelix Manlunas }
297586dea55bSRaghu Vatsavayi 
liquidio_get_vf_config(struct net_device * netdev,int vfidx,struct ifla_vf_info * ivi)297686dea55bSRaghu Vatsavayi static int liquidio_get_vf_config(struct net_device *netdev, int vfidx,
297786dea55bSRaghu Vatsavayi 				  struct ifla_vf_info *ivi)
2978edd572d7SFelix Manlunas {
297986dea55bSRaghu Vatsavayi 	struct lio *lio = GET_LIO(netdev);
298086dea55bSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
298186dea55bSRaghu Vatsavayi 	u8 *macaddr;
298286dea55bSRaghu Vatsavayi 
298386dea55bSRaghu Vatsavayi 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
298486dea55bSRaghu Vatsavayi 		return -EINVAL;
298586dea55bSRaghu Vatsavayi 
298686dea55bSRaghu Vatsavayi 	memset(ivi, 0, sizeof(struct ifla_vf_info));
298786dea55bSRaghu Vatsavayi 
298886dea55bSRaghu Vatsavayi 	ivi->vf = vfidx;
298986dea55bSRaghu Vatsavayi 	macaddr = 2 + (u8 *)&oct->sriov_info.vf_macaddr[vfidx];
299086dea55bSRaghu Vatsavayi 	ether_addr_copy(&ivi->mac[0], macaddr);
299148875222SWeilin Chang 	ivi->vlan = oct->sriov_info.vf_vlantci[vfidx] & VLAN_VID_MASK;
299248875222SWeilin Chang 	ivi->qos = oct->sriov_info.vf_vlantci[vfidx] >> VLAN_PRIO_SHIFT;
299386dea55bSRaghu Vatsavayi 	if (oct->sriov_info.trusted_vf.active &&
299486dea55bSRaghu Vatsavayi 	    oct->sriov_info.trusted_vf.id == vfidx)
299586dea55bSRaghu Vatsavayi 		ivi->trusted = true;
299686dea55bSRaghu Vatsavayi 	else
299786dea55bSRaghu Vatsavayi 		ivi->trusted = false;
2998f2d254faSIntiyaz Basha 	ivi->linkstate = oct->sriov_info.vf_linkstate[vfidx];
2999f2d254faSIntiyaz Basha 	ivi->spoofchk = oct->sriov_info.vf_spoofchk[vfidx];
3000f2d254faSIntiyaz Basha 	ivi->max_tx_rate = lio->linfo.link.s.speed;
3001f2d254faSIntiyaz Basha 	ivi->min_tx_rate = 0;
3002f2d254faSIntiyaz Basha 
300386dea55bSRaghu Vatsavayi 	return 0;
300448875222SWeilin Chang }
300548875222SWeilin Chang 
liquidio_send_vf_trust_cmd(struct lio * lio,int vfidx,bool trusted)300648875222SWeilin Chang static int liquidio_send_vf_trust_cmd(struct lio *lio, int vfidx, bool trusted)
300748875222SWeilin Chang {
300886dea55bSRaghu Vatsavayi 	struct octeon_device *oct = lio->oct_dev;
300986dea55bSRaghu Vatsavayi 	struct octeon_soft_command *sc;
301086dea55bSRaghu Vatsavayi 	int retval;
3011f2d254faSIntiyaz Basha 
3012f2d254faSIntiyaz Basha 	sc = octeon_alloc_soft_command(oct, 0, 16, 0);
3013f2d254faSIntiyaz Basha 	if (!sc)
3014f2d254faSIntiyaz Basha 		return -ENOMEM;
30156870957eSFelix Manlunas 
3016f2d254faSIntiyaz Basha 	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
30176870957eSFelix Manlunas 
30186870957eSFelix Manlunas 	/* vfidx is 0 based, but vf_num (param1) is 1 based */
30196870957eSFelix Manlunas 	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
3020f2d254faSIntiyaz Basha 				    OPCODE_NIC_SET_TRUSTED_VF, 0, vfidx + 1,
3021f2d254faSIntiyaz Basha 				    trusted);
3022f2d254faSIntiyaz Basha 
3023f2d254faSIntiyaz Basha 	init_completion(&sc->complete);
3024f2d254faSIntiyaz Basha 	sc->sc_status = OCTEON_REQUEST_PENDING;
3025f2d254faSIntiyaz Basha 
3026f2d254faSIntiyaz Basha 	retval = octeon_send_soft_command(oct, sc);
3027f2d254faSIntiyaz Basha 	if (retval == IQ_SEND_FAILED) {
30286870957eSFelix Manlunas 		octeon_free_soft_command(oct, sc);
30296870957eSFelix Manlunas 		retval = -1;
3030f2d254faSIntiyaz Basha 	} else {
3031f2d254faSIntiyaz Basha 		/* Wait for response or timeout */
3032f2d254faSIntiyaz Basha 		retval = wait_for_sc_completion_timeout(oct, sc, 0);
30336870957eSFelix Manlunas 		if (retval)
3034f2d254faSIntiyaz Basha 			return (retval);
3035f2d254faSIntiyaz Basha 
3036f2d254faSIntiyaz Basha 		WRITE_ONCE(sc->caller_is_done, true);
30376870957eSFelix Manlunas 	}
30386870957eSFelix Manlunas 
30396870957eSFelix Manlunas 	return retval;
3040f2d254faSIntiyaz Basha }
30416870957eSFelix Manlunas 
liquidio_set_vf_trust(struct net_device * netdev,int vfidx,bool setting)30426870957eSFelix Manlunas static int liquidio_set_vf_trust(struct net_device *netdev, int vfidx,
3043f2d254faSIntiyaz Basha 				 bool setting)
3044f2d254faSIntiyaz Basha {
3045f2d254faSIntiyaz Basha 	struct lio *lio = GET_LIO(netdev);
3046f2d254faSIntiyaz Basha 	struct octeon_device *oct = lio->oct_dev;
3047f2d254faSIntiyaz Basha 
3048f2d254faSIntiyaz Basha 	if (strcmp(oct->fw_info.liquidio_firmware_version, "1.7.1") < 0) {
3049f2d254faSIntiyaz Basha 		/* trusted vf is not supported by firmware older than 1.7.1 */
3050f2d254faSIntiyaz Basha 		return -EOPNOTSUPP;
3051f2d254faSIntiyaz Basha 	}
3052f2d254faSIntiyaz Basha 
3053f2d254faSIntiyaz Basha 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) {
3054f2d254faSIntiyaz Basha 		netif_info(lio, drv, lio->netdev, "Invalid vfidx %d\n", vfidx);
3055f2d254faSIntiyaz Basha 		return -EINVAL;
3056f2d254faSIntiyaz Basha 	}
3057f2d254faSIntiyaz Basha 
3058f2d254faSIntiyaz Basha 	if (setting) {
3059f2d254faSIntiyaz Basha 		/* Set */
3060f2d254faSIntiyaz Basha 
3061f2d254faSIntiyaz Basha 		if (oct->sriov_info.trusted_vf.active &&
3062f2d254faSIntiyaz Basha 		    oct->sriov_info.trusted_vf.id == vfidx)
3063f2d254faSIntiyaz Basha 			return 0;
3064f2d254faSIntiyaz Basha 
3065f2d254faSIntiyaz Basha 		if (oct->sriov_info.trusted_vf.active) {
3066f2d254faSIntiyaz Basha 			netif_info(lio, drv, lio->netdev, "More than one trusted VF is not allowed\n");
3067f2d254faSIntiyaz Basha 			return -EPERM;
3068f2d254faSIntiyaz Basha 		}
3069f2d254faSIntiyaz Basha 	} else {
3070f2d254faSIntiyaz Basha 		/* Clear */
3071f2d254faSIntiyaz Basha 
3072f2d254faSIntiyaz Basha 		if (!oct->sriov_info.trusted_vf.active)
3073f2d254faSIntiyaz Basha 			return 0;
3074f2d254faSIntiyaz Basha 	}
3075f2d254faSIntiyaz Basha 
3076f2d254faSIntiyaz Basha 	if (!liquidio_send_vf_trust_cmd(lio, vfidx, setting)) {
3077f2d254faSIntiyaz Basha 		if (setting) {
3078f2d254faSIntiyaz Basha 			oct->sriov_info.trusted_vf.id = vfidx;
3079f2d254faSIntiyaz Basha 			oct->sriov_info.trusted_vf.active = true;
3080f2d254faSIntiyaz Basha 		} else {
3081f2d254faSIntiyaz Basha 			oct->sriov_info.trusted_vf.active = false;
3082f2d254faSIntiyaz Basha 		}
3083f2d254faSIntiyaz Basha 
3084f2d254faSIntiyaz Basha 		netif_info(lio, drv, lio->netdev, "VF %u is %strusted\n", vfidx,
3085f2d254faSIntiyaz Basha 			   setting ? "" : "not ");
3086f2d254faSIntiyaz Basha 	} else {
3087f2d254faSIntiyaz Basha 		netif_info(lio, drv, lio->netdev, "Failed to set VF trusted\n");
3088f2d254faSIntiyaz Basha 		return -1;
3089f2d254faSIntiyaz Basha 	}
3090f2d254faSIntiyaz Basha 
3091f2d254faSIntiyaz Basha 	return 0;
3092f2d254faSIntiyaz Basha }
3093f2d254faSIntiyaz Basha 
liquidio_set_vf_link_state(struct net_device * netdev,int vfidx,int linkstate)3094f2d254faSIntiyaz Basha static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
3095f2d254faSIntiyaz Basha 				      int linkstate)
3096f2d254faSIntiyaz Basha {
3097f2d254faSIntiyaz Basha 	struct lio *lio = GET_LIO(netdev);
3098f2d254faSIntiyaz Basha 	struct octeon_device *oct = lio->oct_dev;
309986dea55bSRaghu Vatsavayi 	struct octnic_ctrl_pkt nctrl;
310086dea55bSRaghu Vatsavayi 	int ret = 0;
310186dea55bSRaghu Vatsavayi 
310286dea55bSRaghu Vatsavayi 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
310386dea55bSRaghu Vatsavayi 		return -EINVAL;
310486dea55bSRaghu Vatsavayi 
3105edd572d7SFelix Manlunas 	if (oct->sriov_info.vf_linkstate[vfidx] == linkstate)
310686dea55bSRaghu Vatsavayi 		return 0;
310786dea55bSRaghu Vatsavayi 
310886dea55bSRaghu Vatsavayi 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
310986dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_VF_LINKSTATE;
311086dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.param1 =
311186dea55bSRaghu Vatsavayi 	    vfidx + 1; /* vfidx is 0 based, but vf_num (param1) is 1 based */
311286dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.param2 = linkstate;
311386dea55bSRaghu Vatsavayi 	nctrl.ncmd.s.more = 0;
311486dea55bSRaghu Vatsavayi 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
311586dea55bSRaghu Vatsavayi 	nctrl.cb_fn = NULL;
311686dea55bSRaghu Vatsavayi 
311786dea55bSRaghu Vatsavayi 	ret = octnet_send_nic_ctrl_pkt(oct, &nctrl);
311886dea55bSRaghu Vatsavayi 
311986dea55bSRaghu Vatsavayi 	if (!ret)
3120bf20a5c1SYueHaibing 		oct->sriov_info.vf_linkstate[vfidx] = linkstate;
312186dea55bSRaghu Vatsavayi 	else if (ret > 0)
3122edd572d7SFelix Manlunas 		ret = -EIO;
312386dea55bSRaghu Vatsavayi 
3124edd572d7SFelix Manlunas 	return ret;
312586dea55bSRaghu Vatsavayi }
3126edd572d7SFelix Manlunas 
3127edd572d7SFelix Manlunas static int
liquidio_eswitch_mode_get(struct devlink * devlink,u16 * mode)312886dea55bSRaghu Vatsavayi liquidio_eswitch_mode_get(struct devlink *devlink, u16 *mode)
3129edd572d7SFelix Manlunas {
313086dea55bSRaghu Vatsavayi 	struct lio_devlink_priv *priv;
313186dea55bSRaghu Vatsavayi 	struct octeon_device *oct;
31321f233f32SVijaya Mohan Guvva 
3133d4be8ebeSVijaya Mohan Guvva 	priv = devlink_priv(devlink);
3134d4be8ebeSVijaya Mohan Guvva 	oct = priv->oct;
3135d4be8ebeSVijaya Mohan Guvva 
3136d4be8ebeSVijaya Mohan Guvva 	*mode = oct->eswitch_mode;
3137d4be8ebeSVijaya Mohan Guvva 
3138d4be8ebeSVijaya Mohan Guvva 	return 0;
3139d4be8ebeSVijaya Mohan Guvva }
3140d4be8ebeSVijaya Mohan Guvva 
3141d4be8ebeSVijaya Mohan Guvva static int
liquidio_eswitch_mode_set(struct devlink * devlink,u16 mode,struct netlink_ext_ack * extack)3142d4be8ebeSVijaya Mohan Guvva liquidio_eswitch_mode_set(struct devlink *devlink, u16 mode,
3143d4be8ebeSVijaya Mohan Guvva 			  struct netlink_ext_ack *extack)
3144d4be8ebeSVijaya Mohan Guvva {
3145d4be8ebeSVijaya Mohan Guvva 	struct lio_devlink_priv *priv;
3146d4be8ebeSVijaya Mohan Guvva 	struct octeon_device *oct;
3147db7ff19eSEli Britstein 	int ret = 0;
3148db7ff19eSEli Britstein 
3149d4be8ebeSVijaya Mohan Guvva 	priv = devlink_priv(devlink);
3150d4be8ebeSVijaya Mohan Guvva 	oct = priv->oct;
3151d4be8ebeSVijaya Mohan Guvva 
3152d4be8ebeSVijaya Mohan Guvva 	if (!(oct->fw_info.app_cap_flags & LIQUIDIO_SWITCHDEV_CAP))
3153d4be8ebeSVijaya Mohan Guvva 		return -EINVAL;
3154d4be8ebeSVijaya Mohan Guvva 
3155d4be8ebeSVijaya Mohan Guvva 	if (oct->eswitch_mode == mode)
3156d4be8ebeSVijaya Mohan Guvva 		return 0;
3157d4be8ebeSVijaya Mohan Guvva 
3158d4be8ebeSVijaya Mohan Guvva 	switch (mode) {
3159d4be8ebeSVijaya Mohan Guvva 	case DEVLINK_ESWITCH_MODE_SWITCHDEV:
3160d4be8ebeSVijaya Mohan Guvva 		oct->eswitch_mode = mode;
3161d4be8ebeSVijaya Mohan Guvva 		ret = lio_vf_rep_create(oct);
3162d4be8ebeSVijaya Mohan Guvva 		break;
3163d4be8ebeSVijaya Mohan Guvva 
3164d4be8ebeSVijaya Mohan Guvva 	case DEVLINK_ESWITCH_MODE_LEGACY:
3165d4be8ebeSVijaya Mohan Guvva 		lio_vf_rep_destroy(oct);
3166d4be8ebeSVijaya Mohan Guvva 		oct->eswitch_mode = mode;
3167d4be8ebeSVijaya Mohan Guvva 		break;
3168d4be8ebeSVijaya Mohan Guvva 
3169d4be8ebeSVijaya Mohan Guvva 	default:
3170d4be8ebeSVijaya Mohan Guvva 		ret = -EINVAL;
3171d4be8ebeSVijaya Mohan Guvva 	}
3172d4be8ebeSVijaya Mohan Guvva 
3173d4be8ebeSVijaya Mohan Guvva 	return ret;
3174d4be8ebeSVijaya Mohan Guvva }
3175d4be8ebeSVijaya Mohan Guvva 
3176d4be8ebeSVijaya Mohan Guvva static const struct devlink_ops liquidio_devlink_ops = {
3177d4be8ebeSVijaya Mohan Guvva 	.eswitch_mode_get = liquidio_eswitch_mode_get,
3178d4be8ebeSVijaya Mohan Guvva 	.eswitch_mode_set = liquidio_eswitch_mode_set,
3179d4be8ebeSVijaya Mohan Guvva };
3180d4be8ebeSVijaya Mohan Guvva 
3181d4be8ebeSVijaya Mohan Guvva static int
liquidio_get_port_parent_id(struct net_device * dev,struct netdev_phys_item_id * ppid)3182d4be8ebeSVijaya Mohan Guvva liquidio_get_port_parent_id(struct net_device *dev,
3183d4be8ebeSVijaya Mohan Guvva 			    struct netdev_phys_item_id *ppid)
3184d4be8ebeSVijaya Mohan Guvva {
3185d4be8ebeSVijaya Mohan Guvva 	struct lio *lio = GET_LIO(dev);
3186d4be8ebeSVijaya Mohan Guvva 	struct octeon_device *oct = lio->oct_dev;
3187c4bf2450SFlorian Fainelli 
3188c4bf2450SFlorian Fainelli 	if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
31891f233f32SVijaya Mohan Guvva 		return -EOPNOTSUPP;
31901f233f32SVijaya Mohan Guvva 
3191d4be8ebeSVijaya Mohan Guvva 	ppid->id_len = ETH_ALEN;
3192d4be8ebeSVijaya Mohan Guvva 	ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2);
3193d4be8ebeSVijaya Mohan Guvva 
3194d4be8ebeSVijaya Mohan Guvva 	return 0;
31951f233f32SVijaya Mohan Guvva }
3196c4bf2450SFlorian Fainelli 
liquidio_get_vf_stats(struct net_device * netdev,int vfidx,struct ifla_vf_stats * vf_stats)3197c4bf2450SFlorian Fainelli static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx,
31981f233f32SVijaya Mohan Guvva 				 struct ifla_vf_stats *vf_stats)
31991f233f32SVijaya Mohan Guvva {
32001f233f32SVijaya Mohan Guvva 	struct lio *lio = GET_LIO(netdev);
32011f233f32SVijaya Mohan Guvva 	struct octeon_device *oct = lio->oct_dev;
3202cea395acSIntiyaz Basha 	struct oct_vf_stats stats;
3203cea395acSIntiyaz Basha 	int ret;
3204cea395acSIntiyaz Basha 
3205cea395acSIntiyaz Basha 	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
3206cea395acSIntiyaz Basha 		return -EINVAL;
3207cea395acSIntiyaz Basha 
3208cea395acSIntiyaz Basha 	memset(&stats, 0, sizeof(struct oct_vf_stats));
3209cea395acSIntiyaz Basha 	ret = cn23xx_get_vf_stats(oct, vfidx, &stats);
3210cea395acSIntiyaz Basha 	if (!ret) {
3211cea395acSIntiyaz Basha 		vf_stats->rx_packets = stats.rx_packets;
3212cea395acSIntiyaz Basha 		vf_stats->tx_packets = stats.tx_packets;
3213cea395acSIntiyaz Basha 		vf_stats->rx_bytes = stats.rx_bytes;
3214cea395acSIntiyaz Basha 		vf_stats->tx_bytes = stats.tx_bytes;
3215cea395acSIntiyaz Basha 		vf_stats->broadcast = stats.broadcast;
3216cea395acSIntiyaz Basha 		vf_stats->multicast = stats.multicast;
3217cea395acSIntiyaz Basha 	}
3218cea395acSIntiyaz Basha 
3219cea395acSIntiyaz Basha 	return ret;
3220cea395acSIntiyaz Basha }
3221cea395acSIntiyaz Basha 
3222cea395acSIntiyaz Basha static const struct net_device_ops lionetdevops = {
3223cea395acSIntiyaz Basha 	.ndo_open		= liquidio_open,
3224cea395acSIntiyaz Basha 	.ndo_stop		= liquidio_stop,
3225cea395acSIntiyaz Basha 	.ndo_start_xmit		= liquidio_xmit,
3226cea395acSIntiyaz Basha 	.ndo_get_stats64	= liquidio_get_stats64,
322797a25326SRaghu Vatsavayi 	.ndo_set_mac_address	= liquidio_set_mac,
3228f21fb3edSRaghu Vatsavayi 	.ndo_set_rx_mode	= liquidio_set_mcast_list,
3229f21fb3edSRaghu Vatsavayi 	.ndo_tx_timeout		= liquidio_tx_timeout,
3230f21fb3edSRaghu Vatsavayi 
323180002347SPradeep Nalla 	.ndo_vlan_rx_add_vid    = liquidio_vlan_rx_add_vid,
3232f21fb3edSRaghu Vatsavayi 	.ndo_vlan_rx_kill_vid   = liquidio_vlan_rx_kill_vid,
3233f21fb3edSRaghu Vatsavayi 	.ndo_change_mtu		= liquidio_change_mtu,
3234f21fb3edSRaghu Vatsavayi 	.ndo_eth_ioctl		= liquidio_ioctl,
323563245f25SRaghu Vatsavayi 	.ndo_fix_features	= liquidio_fix_features,
323663245f25SRaghu Vatsavayi 	.ndo_set_features	= liquidio_set_features,
323763245f25SRaghu Vatsavayi 	.ndo_set_vf_mac		= liquidio_set_vf_mac,
3238f21fb3edSRaghu Vatsavayi 	.ndo_set_vf_vlan	= liquidio_set_vf_vlan,
3239a7605370SArnd Bergmann 	.ndo_get_vf_config	= liquidio_get_vf_config,
3240f21fb3edSRaghu Vatsavayi 	.ndo_set_vf_spoofchk	= liquidio_set_vf_spoofchk,
3241f21fb3edSRaghu Vatsavayi 	.ndo_set_vf_trust	= liquidio_set_vf_trust,
324286dea55bSRaghu Vatsavayi 	.ndo_set_vf_link_state  = liquidio_set_vf_link_state,
324386dea55bSRaghu Vatsavayi 	.ndo_get_vf_stats	= liquidio_get_vf_stats,
324486dea55bSRaghu Vatsavayi 	.ndo_get_port_parent_id	= liquidio_get_port_parent_id,
324548875222SWeilin Chang };
3246f2d254faSIntiyaz Basha 
324786dea55bSRaghu Vatsavayi /**
3248cea395acSIntiyaz Basha  * liquidio_init - Entry point for the liquidio module
3249c4bf2450SFlorian Fainelli  */
liquidio_init(void)3250f21fb3edSRaghu Vatsavayi static int __init liquidio_init(void)
3251f21fb3edSRaghu Vatsavayi {
3252d0ea5cbdSJesse Brandeburg 	int i;
3253d0ea5cbdSJesse Brandeburg 	struct handshake *hs;
3254f21fb3edSRaghu Vatsavayi 
3255f21fb3edSRaghu Vatsavayi 	init_completion(&first_stage);
3256f21fb3edSRaghu Vatsavayi 
3257f21fb3edSRaghu Vatsavayi 	octeon_init_device_list(OCTEON_CONFIG_TYPE_DEFAULT);
3258f21fb3edSRaghu Vatsavayi 
3259f21fb3edSRaghu Vatsavayi 	if (liquidio_init_pci())
3260f21fb3edSRaghu Vatsavayi 		return -EINVAL;
3261f21fb3edSRaghu Vatsavayi 
326297a25326SRaghu Vatsavayi 	wait_for_completion_timeout(&first_stage, msecs_to_jiffies(1000));
3263f21fb3edSRaghu Vatsavayi 
3264f21fb3edSRaghu Vatsavayi 	for (i = 0; i < MAX_OCTEON_DEVICES; i++) {
3265f21fb3edSRaghu Vatsavayi 		hs = &handshake[i];
3266f21fb3edSRaghu Vatsavayi 		if (hs->pci_dev) {
3267f21fb3edSRaghu Vatsavayi 			wait_for_completion(&hs->init);
3268f21fb3edSRaghu Vatsavayi 			if (!hs->init_ok) {
3269f21fb3edSRaghu Vatsavayi 				/* init handshake failed */
3270f21fb3edSRaghu Vatsavayi 				dev_err(&hs->pci_dev->dev,
3271f21fb3edSRaghu Vatsavayi 					"Failed to init device\n");
3272f21fb3edSRaghu Vatsavayi 				liquidio_deinit_pci();
3273f21fb3edSRaghu Vatsavayi 				return -EIO;
3274f21fb3edSRaghu Vatsavayi 			}
3275f21fb3edSRaghu Vatsavayi 		}
3276f21fb3edSRaghu Vatsavayi 	}
3277f21fb3edSRaghu Vatsavayi 
3278f21fb3edSRaghu Vatsavayi 	for (i = 0; i < MAX_OCTEON_DEVICES; i++) {
3279f21fb3edSRaghu Vatsavayi 		hs = &handshake[i];
3280f21fb3edSRaghu Vatsavayi 		if (hs->pci_dev) {
3281f21fb3edSRaghu Vatsavayi 			wait_for_completion_timeout(&hs->started,
3282f21fb3edSRaghu Vatsavayi 						    msecs_to_jiffies(30000));
3283f21fb3edSRaghu Vatsavayi 			if (!hs->started_ok) {
3284f21fb3edSRaghu Vatsavayi 				/* starter handshake failed */
3285f21fb3edSRaghu Vatsavayi 				dev_err(&hs->pci_dev->dev,
3286f21fb3edSRaghu Vatsavayi 					"Firmware failed to start\n");
3287f21fb3edSRaghu Vatsavayi 				liquidio_deinit_pci();
3288f21fb3edSRaghu Vatsavayi 				return -EIO;
3289f21fb3edSRaghu Vatsavayi 			}
3290f21fb3edSRaghu Vatsavayi 		}
3291f21fb3edSRaghu Vatsavayi 	}
3292f21fb3edSRaghu Vatsavayi 
3293f21fb3edSRaghu Vatsavayi 	return 0;
3294f21fb3edSRaghu Vatsavayi }
3295f21fb3edSRaghu Vatsavayi 
lio_nic_info(struct octeon_recv_info * recv_info,void * buf)3296f21fb3edSRaghu Vatsavayi static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)
3297f21fb3edSRaghu Vatsavayi {
3298f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = (struct octeon_device *)buf;
3299f21fb3edSRaghu Vatsavayi 	struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
3300f21fb3edSRaghu Vatsavayi 	int gmxport = 0;
33015b173cf9SRaghu Vatsavayi 	union oct_link_status *ls;
3302f21fb3edSRaghu Vatsavayi 	int i;
3303f21fb3edSRaghu Vatsavayi 
3304f21fb3edSRaghu Vatsavayi 	if (recv_pkt->buffer_size[0] != (sizeof(*ls) + OCT_DROQ_INFO_SIZE)) {
33050cece6c5SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Malformed NIC_INFO, len=%d, ifidx=%d\n",
3306f21fb3edSRaghu Vatsavayi 			recv_pkt->buffer_size[0],
3307f21fb3edSRaghu Vatsavayi 			recv_pkt->rh.r_nic_info.gmxport);
3308f21fb3edSRaghu Vatsavayi 		goto nic_info_err;
3309c4ee5d81SPrasad Kanneganti 	}
3310f21fb3edSRaghu Vatsavayi 
3311f21fb3edSRaghu Vatsavayi 	gmxport = recv_pkt->rh.r_nic_info.gmxport;
33120cece6c5SRaghu Vatsavayi 	ls = (union oct_link_status *)(get_rbd(recv_pkt->buffer_ptr[0]) +
3313f21fb3edSRaghu Vatsavayi 		OCT_DROQ_INFO_SIZE);
3314f21fb3edSRaghu Vatsavayi 
3315f21fb3edSRaghu Vatsavayi 	octeon_swap_8B_data((u64 *)ls, (sizeof(union oct_link_status)) >> 3);
33160cece6c5SRaghu Vatsavayi 	for (i = 0; i < oct->ifcount; i++) {
3317c4ee5d81SPrasad Kanneganti 		if (oct->props[i].gmxport == gmxport) {
3318c4ee5d81SPrasad Kanneganti 			update_link_status(oct->props[i].netdev, ls);
3319f21fb3edSRaghu Vatsavayi 			break;
3320f21fb3edSRaghu Vatsavayi 		}
33210cece6c5SRaghu Vatsavayi 	}
33220cece6c5SRaghu Vatsavayi 
33230cece6c5SRaghu Vatsavayi nic_info_err:
33240cece6c5SRaghu Vatsavayi 	for (i = 0; i < recv_pkt->buffer_count; i++)
33250cece6c5SRaghu Vatsavayi 		recv_buffer_free(recv_pkt->buffer_ptr[i]);
33260cece6c5SRaghu Vatsavayi 	octeon_free_recv_info(recv_info);
3327f21fb3edSRaghu Vatsavayi 	return 0;
3328f21fb3edSRaghu Vatsavayi }
3329f21fb3edSRaghu Vatsavayi 
3330f21fb3edSRaghu Vatsavayi /**
3331f21fb3edSRaghu Vatsavayi  * setup_nic_devices - Setup network interfaces
3332f21fb3edSRaghu Vatsavayi  * @octeon_dev:  octeon device
3333f21fb3edSRaghu Vatsavayi  *
3334f21fb3edSRaghu Vatsavayi  * Called during init time for each device. It assumes the NIC
3335f21fb3edSRaghu Vatsavayi  * is already up and running.  The link information for each
3336d0ea5cbdSJesse Brandeburg  * interface is passed in link_info.
3337d0ea5cbdSJesse Brandeburg  */
setup_nic_devices(struct octeon_device * octeon_dev)3338f21fb3edSRaghu Vatsavayi static int setup_nic_devices(struct octeon_device *octeon_dev)
3339f21fb3edSRaghu Vatsavayi {
3340f21fb3edSRaghu Vatsavayi 	struct lio *lio = NULL;
3341f21fb3edSRaghu Vatsavayi 	struct net_device *netdev;
3342f21fb3edSRaghu Vatsavayi 	u8 mac[6], i, j, *fw_ver, *micro_ver;
3343f21fb3edSRaghu Vatsavayi 	unsigned long micro;
3344f21fb3edSRaghu Vatsavayi 	u32 cur_ver;
3345f21fb3edSRaghu Vatsavayi 	struct octeon_soft_command *sc;
3346f21fb3edSRaghu Vatsavayi 	struct liquidio_if_cfg_resp *resp;
33474fed38cfSRick Farrington 	struct octdev_props *props;
33484fed38cfSRick Farrington 	int retval, num_iqueues, num_oqueues;
33494fed38cfSRick Farrington 	int max_num_queues = 0;
3350f21fb3edSRaghu Vatsavayi 	union oct_nic_if_cfg if_cfg;
3351f21fb3edSRaghu Vatsavayi 	unsigned int base_queue;
3352f21fb3edSRaghu Vatsavayi 	unsigned int gmx_port_id;
335326236fa9SRaghu Vatsavayi 	u32 resp_size, data_size;
3354c33c9973SIntiyaz Basha 	u32 ifidx_or_pfnum;
3355f21fb3edSRaghu Vatsavayi 	struct lio_version *vdata;
3356f21fb3edSRaghu Vatsavayi 	struct devlink *devlink;
3357f21fb3edSRaghu Vatsavayi 	struct lio_devlink_priv *lio_devlink;
335864fecd3eSFelix Manlunas 
33590cece6c5SRaghu Vatsavayi 	/* This is to handle link status changes */
336083101ce3SRaghu Vatsavayi 	octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC,
3361d4be8ebeSVijaya Mohan Guvva 				    OPCODE_NIC_INFO,
3362d4be8ebeSVijaya Mohan Guvva 				    lio_nic_info, octeon_dev);
3363f21fb3edSRaghu Vatsavayi 
3364f21fb3edSRaghu Vatsavayi 	/* REQTYPE_RESP_NET and REQTYPE_SOFT_COMMAND do not have free functions.
3365f21fb3edSRaghu Vatsavayi 	 * They are handled directly.
3366f21fb3edSRaghu Vatsavayi 	 */
3367f21fb3edSRaghu Vatsavayi 	octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET,
3368f21fb3edSRaghu Vatsavayi 					free_netbuf);
3369f21fb3edSRaghu Vatsavayi 
3370f21fb3edSRaghu Vatsavayi 	octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET_SG,
3371f21fb3edSRaghu Vatsavayi 					free_netsgbuf);
3372f21fb3edSRaghu Vatsavayi 
3373f21fb3edSRaghu Vatsavayi 	octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_RESP_NET_SG,
3374f21fb3edSRaghu Vatsavayi 					free_netsgbuf_with_resp);
3375f21fb3edSRaghu Vatsavayi 
3376f21fb3edSRaghu Vatsavayi 	for (i = 0; i < octeon_dev->ifcount; i++) {
3377f21fb3edSRaghu Vatsavayi 		resp_size = sizeof(struct liquidio_if_cfg_resp);
3378f21fb3edSRaghu Vatsavayi 		data_size = sizeof(struct lio_version);
3379f21fb3edSRaghu Vatsavayi 		sc = (struct octeon_soft_command *)
3380f21fb3edSRaghu Vatsavayi 			octeon_alloc_soft_command(octeon_dev, data_size,
3381f21fb3edSRaghu Vatsavayi 						  resp_size, 0);
3382f21fb3edSRaghu Vatsavayi 		resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
338383101ce3SRaghu Vatsavayi 		vdata = (struct lio_version *)sc->virtdptr;
3384f21fb3edSRaghu Vatsavayi 
338583101ce3SRaghu Vatsavayi 		*((u64 *)vdata) = 0;
338664fecd3eSFelix Manlunas 		vdata->major = cpu_to_be16(LIQUIDIO_BASE_MAJOR_VERSION);
3387f21fb3edSRaghu Vatsavayi 		vdata->minor = cpu_to_be16(LIQUIDIO_BASE_MINOR_VERSION);
338883101ce3SRaghu Vatsavayi 		vdata->micro = cpu_to_be16(LIQUIDIO_BASE_MICRO_VERSION);
338983101ce3SRaghu Vatsavayi 
339083101ce3SRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(octeon_dev)) {
339183101ce3SRaghu Vatsavayi 			num_iqueues = octeon_dev->sriov_info.num_pf_rings;
339283101ce3SRaghu Vatsavayi 			num_oqueues = octeon_dev->sriov_info.num_pf_rings;
339383101ce3SRaghu Vatsavayi 			base_queue = octeon_dev->sriov_info.pf_srn;
3394f21fb3edSRaghu Vatsavayi 
3395e86b1ab6SRaghu Vatsavayi 			gmx_port_id = octeon_dev->pf_num;
3396e86b1ab6SRaghu Vatsavayi 			ifidx_or_pfnum = octeon_dev->pf_num;
3397e86b1ab6SRaghu Vatsavayi 		} else {
3398e86b1ab6SRaghu Vatsavayi 			num_iqueues = CFG_GET_NUM_TXQS_NIC_IF(
3399e86b1ab6SRaghu Vatsavayi 						octeon_get_conf(octeon_dev), i);
3400e86b1ab6SRaghu Vatsavayi 			num_oqueues = CFG_GET_NUM_RXQS_NIC_IF(
3401e86b1ab6SRaghu Vatsavayi 						octeon_get_conf(octeon_dev), i);
3402e86b1ab6SRaghu Vatsavayi 			base_queue = CFG_GET_BASE_QUE_NIC_IF(
3403e86b1ab6SRaghu Vatsavayi 						octeon_get_conf(octeon_dev), i);
3404e86b1ab6SRaghu Vatsavayi 			gmx_port_id = CFG_GET_GMXID_NIC_IF(
3405e86b1ab6SRaghu Vatsavayi 						octeon_get_conf(octeon_dev), i);
3406e86b1ab6SRaghu Vatsavayi 			ifidx_or_pfnum = i;
3407e86b1ab6SRaghu Vatsavayi 		}
3408e86b1ab6SRaghu Vatsavayi 
3409e86b1ab6SRaghu Vatsavayi 		dev_dbg(&octeon_dev->pci_dev->dev,
3410e86b1ab6SRaghu Vatsavayi 			"requesting config for interface %d, iqs %d, oqs %d\n",
34110cece6c5SRaghu Vatsavayi 			ifidx_or_pfnum, num_iqueues, num_oqueues);
3412e86b1ab6SRaghu Vatsavayi 
34133dcef2caSRaghu Vatsavayi 		if_cfg.u64 = 0;
3414f21fb3edSRaghu Vatsavayi 		if_cfg.s.num_iqueues = num_iqueues;
3415f21fb3edSRaghu Vatsavayi 		if_cfg.s.num_oqueues = num_oqueues;
34160cece6c5SRaghu Vatsavayi 		if_cfg.s.base_queue = base_queue;
3417f21fb3edSRaghu Vatsavayi 		if_cfg.s.gmx_port_id = gmx_port_id;
3418f21fb3edSRaghu Vatsavayi 
3419f21fb3edSRaghu Vatsavayi 		sc->iq_no = 0;
3420f21fb3edSRaghu Vatsavayi 
3421f21fb3edSRaghu Vatsavayi 		octeon_prepare_soft_command(octeon_dev, sc, OPCODE_NIC,
3422f21fb3edSRaghu Vatsavayi 					    OPCODE_NIC_IF_CFG, 0,
34230cece6c5SRaghu Vatsavayi 					    if_cfg.u64, 0);
34240cece6c5SRaghu Vatsavayi 
34250cece6c5SRaghu Vatsavayi 		init_completion(&sc->complete);
3426f21fb3edSRaghu Vatsavayi 		sc->sc_status = OCTEON_REQUEST_PENDING;
34270cece6c5SRaghu Vatsavayi 
3428f21fb3edSRaghu Vatsavayi 		retval = octeon_send_soft_command(octeon_dev, sc);
3429f21fb3edSRaghu Vatsavayi 		if (retval == IQ_SEND_FAILED) {
343064fecd3eSFelix Manlunas 			dev_err(&octeon_dev->pci_dev->dev,
343164fecd3eSFelix Manlunas 				"iq/oq config failed status: %x\n",
3432f21fb3edSRaghu Vatsavayi 				retval);
3433f21fb3edSRaghu Vatsavayi 			/* Soft instr is freed by driver in case of failure. */
3434ddc173a6SRaghu Vatsavayi 			octeon_free_soft_command(octeon_dev, sc);
3435f21fb3edSRaghu Vatsavayi 			return(-EIO);
3436f21fb3edSRaghu Vatsavayi 		}
3437f21fb3edSRaghu Vatsavayi 
3438f21fb3edSRaghu Vatsavayi 		/* Sleep on a wait queue till the cond flag indicates that the
343964fecd3eSFelix Manlunas 		 * response arrived or timed-out.
344064fecd3eSFelix Manlunas 		 */
3441f21fb3edSRaghu Vatsavayi 		retval = wait_for_sc_completion_timeout(octeon_dev, sc, 0);
3442f21fb3edSRaghu Vatsavayi 		if (retval)
3443f21fb3edSRaghu Vatsavayi 			return retval;
3444f21fb3edSRaghu Vatsavayi 
3445f21fb3edSRaghu Vatsavayi 		retval = resp->status;
344664fecd3eSFelix Manlunas 		if (retval) {
344764fecd3eSFelix Manlunas 			dev_err(&octeon_dev->pci_dev->dev, "iq/oq config failed\n");
344864fecd3eSFelix Manlunas 			WRITE_ONCE(sc->caller_is_done, true);
3449afdf841fSRaghu Vatsavayi 			goto setup_nic_dev_done;
3450f21fb3edSRaghu Vatsavayi 		}
3451f21fb3edSRaghu Vatsavayi 		snprintf(octeon_dev->fw_info.liquidio_firmware_version,
3452f21fb3edSRaghu Vatsavayi 			 32, "%s",
345364fecd3eSFelix Manlunas 			 resp->cfg_info.liquidio_firmware_version);
345464fecd3eSFelix Manlunas 
3455f21fb3edSRaghu Vatsavayi 		/* Verify f/w version (in case of 'auto' loading from flash) */
345664fecd3eSFelix Manlunas 		fw_ver = octeon_dev->fw_info.liquidio_firmware_version;
345764fecd3eSFelix Manlunas 		if (memcmp(LIQUIDIO_BASE_VERSION,
345864fecd3eSFelix Manlunas 			   fw_ver,
3459f21fb3edSRaghu Vatsavayi 			   strlen(LIQUIDIO_BASE_VERSION))) {
3460b36e4820SRick Farrington 			dev_err(&octeon_dev->pci_dev->dev,
3461b36e4820SRick Farrington 				"Unmatched firmware version. Expected %s.x, got %s.\n",
3462b36e4820SRick Farrington 				LIQUIDIO_BASE_VERSION, fw_ver);
3463b36e4820SRick Farrington 			WRITE_ONCE(sc->caller_is_done, true);
3464b36e4820SRick Farrington 			goto setup_nic_dev_done;
3465b36e4820SRick Farrington 		} else if (atomic_read(octeon_dev->adapter_fw_state) ==
3466b36e4820SRick Farrington 			   FW_IS_PRELOADED) {
3467b36e4820SRick Farrington 			dev_info(&octeon_dev->pci_dev->dev,
346864fecd3eSFelix Manlunas 				 "Using auto-loaded firmware version %s.\n",
346964fecd3eSFelix Manlunas 				 fw_ver);
3470b36e4820SRick Farrington 		}
3471b36e4820SRick Farrington 
3472b36e4820SRick Farrington 		/* extract micro version field; point past '<maj>.<min>.' */
3473b36e4820SRick Farrington 		micro_ver = fw_ver + strlen(LIQUIDIO_BASE_VERSION) + 1;
3474b36e4820SRick Farrington 		if (kstrtoul(micro_ver, 10, &micro) != 0)
3475b36e4820SRick Farrington 			micro = 0;
3476b36e4820SRick Farrington 		octeon_dev->fw_info.ver.maj = LIQUIDIO_BASE_MAJOR_VERSION;
34774fed38cfSRick Farrington 		octeon_dev->fw_info.ver.min = LIQUIDIO_BASE_MINOR_VERSION;
34784fed38cfSRick Farrington 		octeon_dev->fw_info.ver.rev = micro;
34794fed38cfSRick Farrington 
34804fed38cfSRick Farrington 		octeon_swap_8B_data((u64 *)(&resp->cfg_info),
34814fed38cfSRick Farrington 				    (sizeof(struct liquidio_if_cfg_info)) >> 3);
34824fed38cfSRick Farrington 
34834fed38cfSRick Farrington 		num_iqueues = hweight64(resp->cfg_info.iqmask);
34844fed38cfSRick Farrington 		num_oqueues = hweight64(resp->cfg_info.oqmask);
3485f21fb3edSRaghu Vatsavayi 
3486f21fb3edSRaghu Vatsavayi 		if (!(num_iqueues) || !(num_oqueues)) {
3487f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev,
3488f21fb3edSRaghu Vatsavayi 				"Got bad iqueues (%016llx) or oqueues (%016llx) from firmware.\n",
3489f21fb3edSRaghu Vatsavayi 				resp->cfg_info.iqmask,
3490f21fb3edSRaghu Vatsavayi 				resp->cfg_info.oqmask);
3491f21fb3edSRaghu Vatsavayi 			WRITE_ONCE(sc->caller_is_done, true);
3492f21fb3edSRaghu Vatsavayi 			goto setup_nic_dev_done;
3493f21fb3edSRaghu Vatsavayi 		}
3494f21fb3edSRaghu Vatsavayi 
3495f21fb3edSRaghu Vatsavayi 		if (OCTEON_CN6XXX(octeon_dev)) {
349664fecd3eSFelix Manlunas 			max_num_queues = CFG_GET_IQ_MAX_Q(CHIP_CONF(octeon_dev,
349764fecd3eSFelix Manlunas 								    cn6xxx));
3498f21fb3edSRaghu Vatsavayi 		} else if (OCTEON_CN23XX_PF(octeon_dev)) {
3499c33c9973SIntiyaz Basha 			max_num_queues = CFG_GET_IQ_MAX_Q(CHIP_CONF(octeon_dev,
3500c33c9973SIntiyaz Basha 								    cn23xx_pf));
3501c33c9973SIntiyaz Basha 		}
3502c33c9973SIntiyaz Basha 
3503c33c9973SIntiyaz Basha 		dev_dbg(&octeon_dev->pci_dev->dev,
3504c33c9973SIntiyaz Basha 			"interface %d, iqmask %016llx, oqmask %016llx, numiqueues %d, numoqueues %d max_num_queues: %d\n",
3505c33c9973SIntiyaz Basha 			i, resp->cfg_info.iqmask, resp->cfg_info.oqmask,
3506c33c9973SIntiyaz Basha 			num_iqueues, num_oqueues, max_num_queues);
3507c33c9973SIntiyaz Basha 		netdev = alloc_etherdev_mq(LIO_SIZE, max_num_queues);
3508f21fb3edSRaghu Vatsavayi 
3509c33c9973SIntiyaz Basha 		if (!netdev) {
3510f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "Device allocation failed\n");
3511c33c9973SIntiyaz Basha 			WRITE_ONCE(sc->caller_is_done, true);
3512c33c9973SIntiyaz Basha 			goto setup_nic_dev_done;
3513f21fb3edSRaghu Vatsavayi 		}
3514f21fb3edSRaghu Vatsavayi 
3515f21fb3edSRaghu Vatsavayi 		SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev);
351664fecd3eSFelix Manlunas 
351764fecd3eSFelix Manlunas 		/* Associate the routines that will handle different
3518f21fb3edSRaghu Vatsavayi 		 * netdev tasks.
3519f21fb3edSRaghu Vatsavayi 		 */
35200cece6c5SRaghu Vatsavayi 		netdev->netdev_ops = &lionetdevops;
3521f21fb3edSRaghu Vatsavayi 
3522f21fb3edSRaghu Vatsavayi 		retval = netif_set_real_num_rx_queues(netdev, num_oqueues);
3523f21fb3edSRaghu Vatsavayi 		if (retval) {
3524f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev,
3525f21fb3edSRaghu Vatsavayi 				"setting real number rx failed\n");
3526f21fb3edSRaghu Vatsavayi 			WRITE_ONCE(sc->caller_is_done, true);
3527c33c9973SIntiyaz Basha 			goto setup_nic_dev_free;
3528c33c9973SIntiyaz Basha 		}
3529c33c9973SIntiyaz Basha 
3530c33c9973SIntiyaz Basha 		retval = netif_set_real_num_tx_queues(netdev, num_iqueues);
353164fecd3eSFelix Manlunas 		if (retval) {
353264fecd3eSFelix Manlunas 			dev_err(&octeon_dev->pci_dev->dev,
3533c33c9973SIntiyaz Basha 				"setting real number tx failed\n");
3534c33c9973SIntiyaz Basha 			WRITE_ONCE(sc->caller_is_done, true);
3535c33c9973SIntiyaz Basha 			goto setup_nic_dev_free;
3536c33c9973SIntiyaz Basha 		}
3537c33c9973SIntiyaz Basha 
3538c33c9973SIntiyaz Basha 		lio = GET_LIO(netdev);
353964fecd3eSFelix Manlunas 
354064fecd3eSFelix Manlunas 		memset(lio, 0, sizeof(struct lio));
3541c33c9973SIntiyaz Basha 
3542c33c9973SIntiyaz Basha 		lio->ifidx = ifidx_or_pfnum;
3543f21fb3edSRaghu Vatsavayi 
3544f21fb3edSRaghu Vatsavayi 		props = &octeon_dev->props[i];
3545f21fb3edSRaghu Vatsavayi 		props->gmxport = resp->cfg_info.linfo.gmxport;
3546f21fb3edSRaghu Vatsavayi 		props->netdev = netdev;
35470cece6c5SRaghu Vatsavayi 
35480cece6c5SRaghu Vatsavayi 		lio->linfo.num_rxpciq = num_oqueues;
35490cece6c5SRaghu Vatsavayi 		lio->linfo.num_txpciq = num_iqueues;
35500cece6c5SRaghu Vatsavayi 		for (j = 0; j < num_oqueues; j++) {
35510cece6c5SRaghu Vatsavayi 			lio->linfo.rxpciq[j].u64 =
3552f21fb3edSRaghu Vatsavayi 				resp->cfg_info.linfo.rxpciq[j].u64;
3553f21fb3edSRaghu Vatsavayi 		}
3554f21fb3edSRaghu Vatsavayi 		for (j = 0; j < num_iqueues; j++) {
3555f21fb3edSRaghu Vatsavayi 			lio->linfo.txpciq[j].u64 =
355626236fa9SRaghu Vatsavayi 				resp->cfg_info.linfo.txpciq[j].u64;
355726236fa9SRaghu Vatsavayi 		}
3558f21fb3edSRaghu Vatsavayi 		lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr;
3559f21fb3edSRaghu Vatsavayi 		lio->linfo.gmxport = resp->cfg_info.linfo.gmxport;
356026236fa9SRaghu Vatsavayi 		lio->linfo.link.u64 = resp->cfg_info.linfo.link.u64;
356126236fa9SRaghu Vatsavayi 
3562f21fb3edSRaghu Vatsavayi 		WRITE_ONCE(sc->caller_is_done, true);
3563f21fb3edSRaghu Vatsavayi 
3564f21fb3edSRaghu Vatsavayi 		lio->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
3565f21fb3edSRaghu Vatsavayi 
3566f21fb3edSRaghu Vatsavayi 		if (OCTEON_CN23XX_PF(octeon_dev) ||
356764fecd3eSFelix Manlunas 		    OCTEON_CN6XXX(octeon_dev)) {
356864fecd3eSFelix Manlunas 			lio->dev_capability = NETIF_F_HIGHDMA
3569f21fb3edSRaghu Vatsavayi 					      | NETIF_F_IP_CSUM
3570f21fb3edSRaghu Vatsavayi 					      | NETIF_F_IPV6_CSUM
3571e86b1ab6SRaghu Vatsavayi 					      | NETIF_F_SG | NETIF_F_RXCSUM
3572e86b1ab6SRaghu Vatsavayi 					      | NETIF_F_GRO
3573f21fb3edSRaghu Vatsavayi 					      | NETIF_F_TSO | NETIF_F_TSO6
3574e86b1ab6SRaghu Vatsavayi 					      | NETIF_F_LRO;
3575e86b1ab6SRaghu Vatsavayi 		}
3576f21fb3edSRaghu Vatsavayi 		netif_set_tso_max_size(netdev, OCTNIC_GSO_MAX_SIZE);
35770cece6c5SRaghu Vatsavayi 
3578f21fb3edSRaghu Vatsavayi 		/*  Copy of transmit encapsulation capabilities:
3579f21fb3edSRaghu Vatsavayi 		 *  TSO, TSO6, Checksums for this device
3580e86b1ab6SRaghu Vatsavayi 		 */
3581ee8b7a11SJakub Kicinski 		lio->enc_dev_capability = NETIF_F_IP_CSUM
3582f21fb3edSRaghu Vatsavayi 					  | NETIF_F_IPV6_CSUM
358301fb237aSRaghu Vatsavayi 					  | NETIF_F_GSO_UDP_TUNNEL
358401fb237aSRaghu Vatsavayi 					  | NETIF_F_HW_CSUM | NETIF_F_SG
358501fb237aSRaghu Vatsavayi 					  | NETIF_F_RXCSUM
358601fb237aSRaghu Vatsavayi 					  | NETIF_F_TSO | NETIF_F_TSO6
358701fb237aSRaghu Vatsavayi 					  | NETIF_F_LRO;
358801fb237aSRaghu Vatsavayi 
358901fb237aSRaghu Vatsavayi 		netdev->hw_enc_features = (lio->enc_dev_capability &
359001fb237aSRaghu Vatsavayi 					   ~NETIF_F_LRO);
359101fb237aSRaghu Vatsavayi 
359201fb237aSRaghu Vatsavayi 		netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
359301fb237aSRaghu Vatsavayi 
359401fb237aSRaghu Vatsavayi 		lio->dev_capability |= NETIF_F_GSO_UDP_TUNNEL;
359501fb237aSRaghu Vatsavayi 
359601fb237aSRaghu Vatsavayi 		netdev->vlan_features = lio->dev_capability;
35973fcd2ba1SJakub Kicinski 		/* Add any unchangeable hw features */
35983fcd2ba1SJakub Kicinski 		lio->dev_capability |=  NETIF_F_HW_VLAN_CTAG_FILTER |
359901fb237aSRaghu Vatsavayi 					NETIF_F_HW_VLAN_CTAG_RX |
360001fb237aSRaghu Vatsavayi 					NETIF_F_HW_VLAN_CTAG_TX;
36010da0b77cSRaghu Vatsavayi 
36020da0b77cSRaghu Vatsavayi 		netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
360363245f25SRaghu Vatsavayi 
360463245f25SRaghu Vatsavayi 		netdev->hw_features = lio->dev_capability;
36050da0b77cSRaghu Vatsavayi 		/*HW_VLAN_RX and HW_VLAN_FILTER is always on*/
36060da0b77cSRaghu Vatsavayi 		netdev->hw_features = netdev->hw_features &
36070cece6c5SRaghu Vatsavayi 			~NETIF_F_HW_VLAN_CTAG_RX;
36080cece6c5SRaghu Vatsavayi 
3609f21fb3edSRaghu Vatsavayi 		/* MTU range: 68 - 16000 */
36100da0b77cSRaghu Vatsavayi 		netdev->min_mtu = LIO_MIN_MTU_SIZE;
36110da0b77cSRaghu Vatsavayi 		netdev->max_mtu = LIO_MAX_MTU_SIZE;
36120da0b77cSRaghu Vatsavayi 
3613f21fb3edSRaghu Vatsavayi 		/* Point to the  properties for octeon device to which this
3614109cc165SJarod Wilson 		 * interface belongs.
3615109cc165SJarod Wilson 		 */
3616109cc165SJarod Wilson 		lio->oct_dev = octeon_dev;
3617109cc165SJarod Wilson 		lio->octprops = props;
3618f21fb3edSRaghu Vatsavayi 		lio->netdev = netdev;
3619f21fb3edSRaghu Vatsavayi 
3620f21fb3edSRaghu Vatsavayi 		dev_dbg(&octeon_dev->pci_dev->dev,
3621f21fb3edSRaghu Vatsavayi 			"if%d gmx: %d hw_addr: 0x%llx\n", i,
3622f21fb3edSRaghu Vatsavayi 			lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr));
3623f21fb3edSRaghu Vatsavayi 
3624f21fb3edSRaghu Vatsavayi 		for (j = 0; j < octeon_dev->sriov_info.max_vfs; j++) {
3625f21fb3edSRaghu Vatsavayi 			u8 vfmac[ETH_ALEN];
3626f21fb3edSRaghu Vatsavayi 
3627f21fb3edSRaghu Vatsavayi 			eth_random_addr(vfmac);
3628f21fb3edSRaghu Vatsavayi 			if (__liquidio_set_vf_mac(netdev, j, vfmac, false)) {
362986dea55bSRaghu Vatsavayi 				dev_err(&octeon_dev->pci_dev->dev,
363086dea55bSRaghu Vatsavayi 					"Error setting VF%d MAC address\n",
363186dea55bSRaghu Vatsavayi 					j);
36326c1f0a1fSJoe Perches 				goto setup_nic_dev_free;
36336c1f0a1fSJoe Perches 			}
363486dea55bSRaghu Vatsavayi 		}
363586dea55bSRaghu Vatsavayi 
363686dea55bSRaghu Vatsavayi 		/* 64-bit swap required on LE machines */
363764fecd3eSFelix Manlunas 		octeon_swap_8B_data(&lio->linfo.hw_addr, 1);
363886dea55bSRaghu Vatsavayi 		for (j = 0; j < 6; j++)
363986dea55bSRaghu Vatsavayi 			mac[j] = *((u8 *)(((u8 *)&lio->linfo.hw_addr) + 2 + j));
364086dea55bSRaghu Vatsavayi 
3641f21fb3edSRaghu Vatsavayi 		/* Copy MAC Address to OS network device structure */
3642f21fb3edSRaghu Vatsavayi 
3643f21fb3edSRaghu Vatsavayi 		eth_hw_addr_set(netdev, mac);
3644f21fb3edSRaghu Vatsavayi 
3645f21fb3edSRaghu Vatsavayi 		/* By default all interfaces on a single Octeon uses the same
3646f21fb3edSRaghu Vatsavayi 		 * tx and rx queues
3647f21fb3edSRaghu Vatsavayi 		 */
3648f3956ebbSJakub Kicinski 		lio->txq = lio->linfo.txpciq[0].s.q_no;
3649f21fb3edSRaghu Vatsavayi 		lio->rxq = lio->linfo.rxpciq[0].s.q_no;
365026236fa9SRaghu Vatsavayi 		if (liquidio_setup_io_queues(octeon_dev, i,
365126236fa9SRaghu Vatsavayi 					     lio->linfo.num_txpciq,
365226236fa9SRaghu Vatsavayi 					     lio->linfo.num_rxpciq)) {
365326236fa9SRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "I/O queues creation failed\n");
365426236fa9SRaghu Vatsavayi 			goto setup_nic_dev_free;
3655a82457f1SIntiyaz Basha 		}
3656a82457f1SIntiyaz Basha 
3657a82457f1SIntiyaz Basha 		ifstate_set(lio, LIO_IFSTATE_DROQ_OPS);
3658f21fb3edSRaghu Vatsavayi 
365964fecd3eSFelix Manlunas 		lio->tx_qsize = octeon_get_tx_qsize(octeon_dev, lio->txq);
3660f21fb3edSRaghu Vatsavayi 		lio->rx_qsize = octeon_get_rx_qsize(octeon_dev, lio->rxq);
3661f21fb3edSRaghu Vatsavayi 
3662f21fb3edSRaghu Vatsavayi 		if (lio_setup_glists(octeon_dev, lio, num_iqueues)) {
3663f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev,
3664f21fb3edSRaghu Vatsavayi 				"Gather list allocation failed\n");
3665f21fb3edSRaghu Vatsavayi 			goto setup_nic_dev_free;
3666f21fb3edSRaghu Vatsavayi 		}
3667128ea394SIntiyaz Basha 
3668f21fb3edSRaghu Vatsavayi 		/* Register ethtool support */
3669f21fb3edSRaghu Vatsavayi 		liquidio_set_ethtool_ops(netdev);
367064fecd3eSFelix Manlunas 		if (lio->oct_dev->chip_id == OCTEON_CN23XX_PF_VID)
3671f21fb3edSRaghu Vatsavayi 			octeon_dev->priv_flags = OCT_PRIV_FLAG_DEFAULT;
3672f21fb3edSRaghu Vatsavayi 		else
3673f21fb3edSRaghu Vatsavayi 			octeon_dev->priv_flags = 0x0;
3674f21fb3edSRaghu Vatsavayi 
367530136395SRaghu Vatsavayi 		if (netdev->features & NETIF_F_LRO)
367630136395SRaghu Vatsavayi 			liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
367730136395SRaghu Vatsavayi 					     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
3678f5a20472SRaghu Vatsavayi 
3679f21fb3edSRaghu Vatsavayi 		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL,
36800cece6c5SRaghu Vatsavayi 				     OCTNET_CMD_VLAN_FILTER_ENABLE);
36810cece6c5SRaghu Vatsavayi 
36820cece6c5SRaghu Vatsavayi 		if ((debug != -1) && (debug & NETIF_MSG_HW))
3683f21fb3edSRaghu Vatsavayi 			liquidio_set_feature(netdev,
3684836d57e5SPrasad Kanneganti 					     OCTNET_CMD_VERBOSE_ENABLE, 0);
3685836d57e5SPrasad Kanneganti 
368663245f25SRaghu Vatsavayi 		if (setup_link_status_change_wq(netdev))
3687f21fb3edSRaghu Vatsavayi 			goto setup_nic_dev_free;
368863245f25SRaghu Vatsavayi 
368963245f25SRaghu Vatsavayi 		if ((octeon_dev->fw_info.app_cap_flags &
3690f21fb3edSRaghu Vatsavayi 		     LIQUIDIO_TIME_SYNC_CAP) &&
36917b6b6c95SRaghu Vatsavayi 		    setup_sync_octeon_time_wq(netdev))
369264fecd3eSFelix Manlunas 			goto setup_nic_dev_free;
36937b6b6c95SRaghu Vatsavayi 
3694907aaa6bSVeerasenareddy Burru 		if (setup_rx_oom_poll_fn(netdev))
3695907aaa6bSVeerasenareddy Burru 			goto setup_nic_dev_free;
3696907aaa6bSVeerasenareddy Burru 
369764fecd3eSFelix Manlunas 		/* Register the network device with the OS */
3698907aaa6bSVeerasenareddy Burru 		if (register_netdev(netdev)) {
3699031d4f12SSatanand Burla 			dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
370064fecd3eSFelix Manlunas 			goto setup_nic_dev_free;
3701031d4f12SSatanand Burla 		}
3702f21fb3edSRaghu Vatsavayi 
3703f21fb3edSRaghu Vatsavayi 		dev_dbg(&octeon_dev->pci_dev->dev,
3704f21fb3edSRaghu Vatsavayi 			"Setup NIC ifidx:%d mac:%02x%02x%02x%02x%02x%02x\n",
370564fecd3eSFelix Manlunas 			i, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
3706f21fb3edSRaghu Vatsavayi 		netif_carrier_off(netdev);
3707f21fb3edSRaghu Vatsavayi 		lio->link_changes++;
3708f21fb3edSRaghu Vatsavayi 
3709f21fb3edSRaghu Vatsavayi 		ifstate_set(lio, LIO_IFSTATE_REGISTERED);
3710f21fb3edSRaghu Vatsavayi 
3711f21fb3edSRaghu Vatsavayi 		/* Sending command to firmware to enable Rx checksum offload
37120cece6c5SRaghu Vatsavayi 		 * by default at the time of setup of Liquidio driver for
3713f21fb3edSRaghu Vatsavayi 		 * this device
3714f21fb3edSRaghu Vatsavayi 		 */
3715f21fb3edSRaghu Vatsavayi 		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
371601fb237aSRaghu Vatsavayi 					    OCTNET_CMD_RXCSUM_ENABLE);
371701fb237aSRaghu Vatsavayi 		liquidio_set_feature(netdev, OCTNET_CMD_TNL_TX_CSUM_CTL,
371801fb237aSRaghu Vatsavayi 				     OCTNET_CMD_TXCSUM_ENABLE);
371901fb237aSRaghu Vatsavayi 
372001fb237aSRaghu Vatsavayi 		dev_dbg(&octeon_dev->pci_dev->dev,
372101fb237aSRaghu Vatsavayi 			"NIC ifidx:%d Setup successful\n", i);
372201fb237aSRaghu Vatsavayi 
372301fb237aSRaghu Vatsavayi 		if (octeon_dev->subsystem_id ==
372401fb237aSRaghu Vatsavayi 			OCTEON_CN2350_25GB_SUBSYS_ID ||
3725f21fb3edSRaghu Vatsavayi 		    octeon_dev->subsystem_id ==
3726f21fb3edSRaghu Vatsavayi 			OCTEON_CN2360_25GB_SUBSYS_ID) {
3727f21fb3edSRaghu Vatsavayi 			cur_ver = OCT_FW_VER(octeon_dev->fw_info.ver.maj,
372818b338f5SWeilin Chang 					     octeon_dev->fw_info.ver.min,
372918b338f5SWeilin Chang 					     octeon_dev->fw_info.ver.rev);
373018b338f5SWeilin Chang 
373118b338f5SWeilin Chang 			/* speed control unsupported in f/w older than 1.7.2 */
37324fed38cfSRick Farrington 			if (cur_ver < OCT_FW_VER(1, 7, 2)) {
37334fed38cfSRick Farrington 				dev_info(&octeon_dev->pci_dev->dev,
37344fed38cfSRick Farrington 					 "speed setting not supported by f/w.");
37354fed38cfSRick Farrington 				octeon_dev->speed_setting = 25;
37364fed38cfSRick Farrington 				octeon_dev->no_speed_setting = 1;
37374fed38cfSRick Farrington 			} else {
37384fed38cfSRick Farrington 				liquidio_get_speed(lio);
37394fed38cfSRick Farrington 			}
37404fed38cfSRick Farrington 
37414fed38cfSRick Farrington 			if (octeon_dev->speed_setting == 0) {
37424fed38cfSRick Farrington 				octeon_dev->speed_setting = 25;
374318b338f5SWeilin Chang 				octeon_dev->no_speed_setting = 1;
37444fed38cfSRick Farrington 			}
374518b338f5SWeilin Chang 		} else {
374618b338f5SWeilin Chang 			octeon_dev->no_speed_setting = 1;
374718b338f5SWeilin Chang 			octeon_dev->speed_setting = 10;
374818b338f5SWeilin Chang 		}
374918b338f5SWeilin Chang 		octeon_dev->speed_boot = octeon_dev->speed_setting;
375018b338f5SWeilin Chang 
375118b338f5SWeilin Chang 		/* don't read FEC setting if unsupported by f/w (see above) */
375218b338f5SWeilin Chang 		if (octeon_dev->speed_boot == 25 &&
375318b338f5SWeilin Chang 		    !octeon_dev->no_speed_setting) {
375418b338f5SWeilin Chang 			liquidio_get_fec(lio);
375575b2c206SWeilin Chang 			octeon_dev->props[lio->ifidx].fec_boot =
375675b2c206SWeilin Chang 				octeon_dev->props[lio->ifidx].fec;
375775b2c206SWeilin Chang 		}
375875b2c206SWeilin Chang 	}
375975b2c206SWeilin Chang 
376075b2c206SWeilin Chang 	device_lock(&octeon_dev->pci_dev->dev);
376175b2c206SWeilin Chang 	devlink = devlink_alloc(&liquidio_devlink_ops,
376275b2c206SWeilin Chang 				sizeof(struct lio_devlink_priv),
3763f21fb3edSRaghu Vatsavayi 				&octeon_dev->pci_dev->dev);
3764f21fb3edSRaghu Vatsavayi 	if (!devlink) {
37658d44b5cfSLeon Romanovsky 		device_unlock(&octeon_dev->pci_dev->dev);
3766d4be8ebeSVijaya Mohan Guvva 		dev_err(&octeon_dev->pci_dev->dev, "devlink alloc failed\n");
3767919d13a7SLeon Romanovsky 		goto setup_nic_dev_free;
3768919d13a7SLeon Romanovsky 	}
3769d4be8ebeSVijaya Mohan Guvva 
37708d44b5cfSLeon Romanovsky 	lio_devlink = devlink_priv(devlink);
3771d4be8ebeSVijaya Mohan Guvva 	lio_devlink->oct = octeon_dev;
377264fecd3eSFelix Manlunas 
3773d4be8ebeSVijaya Mohan Guvva 	octeon_dev->devlink = devlink;
3774d4be8ebeSVijaya Mohan Guvva 	octeon_dev->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
3775d4be8ebeSVijaya Mohan Guvva 	devlink_register(devlink);
3776d4be8ebeSVijaya Mohan Guvva 	device_unlock(&octeon_dev->pci_dev->dev);
3777d4be8ebeSVijaya Mohan Guvva 
3778d4be8ebeSVijaya Mohan Guvva 	return 0;
3779d4be8ebeSVijaya Mohan Guvva 
37808d44b5cfSLeon Romanovsky setup_nic_dev_free:
37818d44b5cfSLeon Romanovsky 
3782d4be8ebeSVijaya Mohan Guvva 	while (i--) {
3783f21fb3edSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev,
3784f21fb3edSRaghu Vatsavayi 			"NIC ifidx:%d Setup failed\n", i);
378564fecd3eSFelix Manlunas 		liquidio_destroy_nic_device(octeon_dev, i);
3786afdf841fSRaghu Vatsavayi 	}
3787f21fb3edSRaghu Vatsavayi 
3788f21fb3edSRaghu Vatsavayi setup_nic_dev_done:
3789f21fb3edSRaghu Vatsavayi 
3790f21fb3edSRaghu Vatsavayi 	return -ENODEV;
3791f21fb3edSRaghu Vatsavayi }
379264fecd3eSFelix Manlunas 
379364fecd3eSFelix Manlunas #ifdef CONFIG_PCI_IOV
octeon_enable_sriov(struct octeon_device * oct)379464fecd3eSFelix Manlunas static int octeon_enable_sriov(struct octeon_device *oct)
3795f21fb3edSRaghu Vatsavayi {
3796f21fb3edSRaghu Vatsavayi 	unsigned int num_vfs_alloced = oct->sriov_info.num_vfs_alloced;
3797f21fb3edSRaghu Vatsavayi 	struct pci_dev *vfdev;
3798ca6139ffSRaghu Vatsavayi 	int err;
3799ca6139ffSRaghu Vatsavayi 	u32 u;
3800ca6139ffSRaghu Vatsavayi 
3801ca6139ffSRaghu Vatsavayi 	if (OCTEON_CN23XX_PF(oct) && num_vfs_alloced) {
3802ca6139ffSRaghu Vatsavayi 		err = pci_enable_sriov(oct->pci_dev,
3803ca6139ffSRaghu Vatsavayi 				       oct->sriov_info.num_vfs_alloced);
3804ca6139ffSRaghu Vatsavayi 		if (err) {
3805ca6139ffSRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev,
3806ca6139ffSRaghu Vatsavayi 				"OCTEON: Failed to enable PCI sriov: %d\n",
3807ca6139ffSRaghu Vatsavayi 				err);
3808ca6139ffSRaghu Vatsavayi 			oct->sriov_info.num_vfs_alloced = 0;
3809ca6139ffSRaghu Vatsavayi 			return err;
3810ca6139ffSRaghu Vatsavayi 		}
3811ca6139ffSRaghu Vatsavayi 		oct->sriov_info.sriov_enabled = 1;
3812ca6139ffSRaghu Vatsavayi 
3813ca6139ffSRaghu Vatsavayi 		/* init lookup table that maps DPI ring number to VF pci_dev
3814ca6139ffSRaghu Vatsavayi 		 * struct pointer
3815ca6139ffSRaghu Vatsavayi 		 */
3816ca6139ffSRaghu Vatsavayi 		u = 0;
3817ca6139ffSRaghu Vatsavayi 		vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
3818ca6139ffSRaghu Vatsavayi 				       OCTEON_CN23XX_VF_VID, NULL);
3819ca6139ffSRaghu Vatsavayi 		while (vfdev) {
3820ca6139ffSRaghu Vatsavayi 			if (vfdev->is_virtfn &&
3821ca6139ffSRaghu Vatsavayi 			    (vfdev->physfn == oct->pci_dev)) {
3822ca6139ffSRaghu Vatsavayi 				oct->sriov_info.dpiring_to_vfpcidev_lut[u] =
3823ca6139ffSRaghu Vatsavayi 					vfdev;
3824ca6139ffSRaghu Vatsavayi 				u += oct->sriov_info.rings_per_vf;
3825ca6139ffSRaghu Vatsavayi 			}
3826ca6139ffSRaghu Vatsavayi 			vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
3827ca6139ffSRaghu Vatsavayi 					       OCTEON_CN23XX_VF_VID, vfdev);
3828ca6139ffSRaghu Vatsavayi 		}
3829ca6139ffSRaghu Vatsavayi 	}
3830ca6139ffSRaghu Vatsavayi 
3831ca6139ffSRaghu Vatsavayi 	return num_vfs_alloced;
3832ca6139ffSRaghu Vatsavayi }
3833ca6139ffSRaghu Vatsavayi 
lio_pci_sriov_disable(struct octeon_device * oct)3834ca6139ffSRaghu Vatsavayi static int lio_pci_sriov_disable(struct octeon_device *oct)
3835ca6139ffSRaghu Vatsavayi {
3836ca6139ffSRaghu Vatsavayi 	int u;
3837ca6139ffSRaghu Vatsavayi 
3838ca6139ffSRaghu Vatsavayi 	if (pci_vfs_assigned(oct->pci_dev)) {
3839ca6139ffSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "VFs are still assigned to VMs.\n");
3840ca6139ffSRaghu Vatsavayi 		return -EPERM;
3841ca6139ffSRaghu Vatsavayi 	}
3842ca6139ffSRaghu Vatsavayi 
3843ca6139ffSRaghu Vatsavayi 	pci_disable_sriov(oct->pci_dev);
3844ca6139ffSRaghu Vatsavayi 
3845ca6139ffSRaghu Vatsavayi 	u = 0;
3846ca6139ffSRaghu Vatsavayi 	while (u < MAX_POSSIBLE_VFS) {
3847ca6139ffSRaghu Vatsavayi 		oct->sriov_info.dpiring_to_vfpcidev_lut[u] = NULL;
3848ca6139ffSRaghu Vatsavayi 		u += oct->sriov_info.rings_per_vf;
3849ca6139ffSRaghu Vatsavayi 	}
3850ca6139ffSRaghu Vatsavayi 
3851ca6139ffSRaghu Vatsavayi 	oct->sriov_info.num_vfs_alloced = 0;
3852ca6139ffSRaghu Vatsavayi 	dev_info(&oct->pci_dev->dev, "oct->pf_num:%d disabled VFs\n",
3853ca6139ffSRaghu Vatsavayi 		 oct->pf_num);
3854ca6139ffSRaghu Vatsavayi 
3855ca6139ffSRaghu Vatsavayi 	return 0;
3856ca6139ffSRaghu Vatsavayi }
3857ca6139ffSRaghu Vatsavayi 
liquidio_enable_sriov(struct pci_dev * dev,int num_vfs)3858ca6139ffSRaghu Vatsavayi static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs)
3859ca6139ffSRaghu Vatsavayi {
3860ca6139ffSRaghu Vatsavayi 	struct octeon_device *oct = pci_get_drvdata(dev);
3861ca6139ffSRaghu Vatsavayi 	int ret = 0;
3862ca6139ffSRaghu Vatsavayi 
3863ca6139ffSRaghu Vatsavayi 	if ((num_vfs == oct->sriov_info.num_vfs_alloced) &&
3864ca6139ffSRaghu Vatsavayi 	    (oct->sriov_info.sriov_enabled)) {
3865ca6139ffSRaghu Vatsavayi 		dev_info(&oct->pci_dev->dev, "oct->pf_num:%d already enabled num_vfs:%d\n",
3866ca6139ffSRaghu Vatsavayi 			 oct->pf_num, num_vfs);
3867ca6139ffSRaghu Vatsavayi 		return 0;
3868ca6139ffSRaghu Vatsavayi 	}
3869ca6139ffSRaghu Vatsavayi 
3870ca6139ffSRaghu Vatsavayi 	if (!num_vfs) {
3871ca6139ffSRaghu Vatsavayi 		lio_vf_rep_destroy(oct);
3872ca6139ffSRaghu Vatsavayi 		ret = lio_pci_sriov_disable(oct);
3873ca6139ffSRaghu Vatsavayi 	} else if (num_vfs > oct->sriov_info.max_vfs) {
3874ca6139ffSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev,
3875ca6139ffSRaghu Vatsavayi 			"OCTEON: Max allowed VFs:%d user requested:%d",
3876d4be8ebeSVijaya Mohan Guvva 			oct->sriov_info.max_vfs, num_vfs);
3877ca6139ffSRaghu Vatsavayi 		ret = -EPERM;
3878ca6139ffSRaghu Vatsavayi 	} else {
3879ca6139ffSRaghu Vatsavayi 		oct->sriov_info.num_vfs_alloced = num_vfs;
3880ca6139ffSRaghu Vatsavayi 		ret = octeon_enable_sriov(oct);
3881ca6139ffSRaghu Vatsavayi 		dev_info(&oct->pci_dev->dev, "oct->pf_num:%d num_vfs:%d\n",
3882ca6139ffSRaghu Vatsavayi 			 oct->pf_num, num_vfs);
3883ca6139ffSRaghu Vatsavayi 		ret = lio_vf_rep_create(oct);
3884ca6139ffSRaghu Vatsavayi 		if (ret)
3885ca6139ffSRaghu Vatsavayi 			dev_info(&oct->pci_dev->dev,
3886ca6139ffSRaghu Vatsavayi 				 "vf representor create failed");
3887ca6139ffSRaghu Vatsavayi 	}
3888d4be8ebeSVijaya Mohan Guvva 
3889d4be8ebeSVijaya Mohan Guvva 	return ret;
3890d4be8ebeSVijaya Mohan Guvva }
3891d4be8ebeSVijaya Mohan Guvva #endif
3892ca6139ffSRaghu Vatsavayi 
3893ca6139ffSRaghu Vatsavayi /**
3894ca6139ffSRaghu Vatsavayi  * liquidio_init_nic_module - initialize the NIC
3895ca6139ffSRaghu Vatsavayi  * @oct: octeon device
3896ca6139ffSRaghu Vatsavayi  *
3897ca6139ffSRaghu Vatsavayi  * This initialization routine is called once the Octeon device application is
3898f21fb3edSRaghu Vatsavayi  * up and running
3899d0ea5cbdSJesse Brandeburg  */
liquidio_init_nic_module(struct octeon_device * oct)3900d0ea5cbdSJesse Brandeburg static int liquidio_init_nic_module(struct octeon_device *oct)
3901f21fb3edSRaghu Vatsavayi {
3902f21fb3edSRaghu Vatsavayi 	int i, retval = 0;
3903f21fb3edSRaghu Vatsavayi 	int num_nic_ports = CFG_GET_NUM_NIC_PORTS(octeon_get_conf(oct));
3904f21fb3edSRaghu Vatsavayi 
3905f21fb3edSRaghu Vatsavayi 	dev_dbg(&oct->pci_dev->dev, "Initializing network interfaces\n");
3906f21fb3edSRaghu Vatsavayi 
39070cece6c5SRaghu Vatsavayi 	/* only default iq and oq were initialized
3908f21fb3edSRaghu Vatsavayi 	 * initialize the rest as well
3909f21fb3edSRaghu Vatsavayi 	 */
3910f21fb3edSRaghu Vatsavayi 	/* run port_config command for each port */
3911f21fb3edSRaghu Vatsavayi 	oct->ifcount = num_nic_ports;
3912f21fb3edSRaghu Vatsavayi 
3913f21fb3edSRaghu Vatsavayi 	memset(oct->props, 0, sizeof(struct octdev_props) * num_nic_ports);
3914f21fb3edSRaghu Vatsavayi 
3915f21fb3edSRaghu Vatsavayi 	for (i = 0; i < MAX_OCTEON_LINKS; i++)
3916f21fb3edSRaghu Vatsavayi 		oct->props[i].gmxport = -1;
3917f21fb3edSRaghu Vatsavayi 
391830136395SRaghu Vatsavayi 	retval = setup_nic_devices(oct);
3919f21fb3edSRaghu Vatsavayi 	if (retval) {
39200cece6c5SRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev, "Setup NIC devices failed\n");
39210cece6c5SRaghu Vatsavayi 		goto octnet_init_failure;
39220cece6c5SRaghu Vatsavayi 	}
3923f21fb3edSRaghu Vatsavayi 
3924f21fb3edSRaghu Vatsavayi 	/* Call vf_rep_modinit if the firmware is switchdev capable
3925f21fb3edSRaghu Vatsavayi 	 * and do it from the first liquidio function probed.
3926f21fb3edSRaghu Vatsavayi 	 */
3927f21fb3edSRaghu Vatsavayi 	if (!oct->octeon_id &&
3928f21fb3edSRaghu Vatsavayi 	    oct->fw_info.app_cap_flags & LIQUIDIO_SWITCHDEV_CAP) {
3929e20f4696SVijaya Mohan Guvva 		retval = lio_vf_rep_modinit();
3930e20f4696SVijaya Mohan Guvva 		if (retval) {
3931e20f4696SVijaya Mohan Guvva 			liquidio_stop_nic_module(oct);
3932e20f4696SVijaya Mohan Guvva 			goto octnet_init_failure;
3933e20f4696SVijaya Mohan Guvva 		}
3934228aa012SDan Carpenter 	}
3935228aa012SDan Carpenter 
3936e20f4696SVijaya Mohan Guvva 	liquidio_ptp_init(oct);
3937e20f4696SVijaya Mohan Guvva 
3938e20f4696SVijaya Mohan Guvva 	dev_dbg(&oct->pci_dev->dev, "Network interfaces ready\n");
3939e20f4696SVijaya Mohan Guvva 
3940e20f4696SVijaya Mohan Guvva 	return retval;
3941f21fb3edSRaghu Vatsavayi 
3942f21fb3edSRaghu Vatsavayi octnet_init_failure:
3943f21fb3edSRaghu Vatsavayi 
3944f21fb3edSRaghu Vatsavayi 	oct->ifcount = 0;
3945f21fb3edSRaghu Vatsavayi 
3946f21fb3edSRaghu Vatsavayi 	return retval;
3947f21fb3edSRaghu Vatsavayi }
3948f21fb3edSRaghu Vatsavayi 
3949f21fb3edSRaghu Vatsavayi /**
3950f21fb3edSRaghu Vatsavayi  * nic_starter - finish init
3951f21fb3edSRaghu Vatsavayi  * @work:  work struct work_struct
3952f21fb3edSRaghu Vatsavayi  *
3953f21fb3edSRaghu Vatsavayi  * starter callback that invokes the remaining initialization work after the NIC is up and running.
3954f21fb3edSRaghu Vatsavayi  */
nic_starter(struct work_struct * work)3955d0ea5cbdSJesse Brandeburg static void nic_starter(struct work_struct *work)
3956d0ea5cbdSJesse Brandeburg {
3957d0ea5cbdSJesse Brandeburg 	struct octeon_device *oct;
3958d0ea5cbdSJesse Brandeburg 	struct cavium_wk *wk = (struct cavium_wk *)work;
3959f21fb3edSRaghu Vatsavayi 
3960f21fb3edSRaghu Vatsavayi 	oct = (struct octeon_device *)wk->ctxptr;
3961f21fb3edSRaghu Vatsavayi 
3962f21fb3edSRaghu Vatsavayi 	if (atomic_read(&oct->status) == OCT_DEV_RUNNING)
3963f21fb3edSRaghu Vatsavayi 		return;
3964f21fb3edSRaghu Vatsavayi 
3965f21fb3edSRaghu Vatsavayi 	/* If the status of the device is CORE_OK, the core
3966f21fb3edSRaghu Vatsavayi 	 * application has reported its application type. Call
3967f21fb3edSRaghu Vatsavayi 	 * any registered handlers now and move to the RUNNING
3968f21fb3edSRaghu Vatsavayi 	 * state.
3969f21fb3edSRaghu Vatsavayi 	 */
3970f21fb3edSRaghu Vatsavayi 	if (atomic_read(&oct->status) != OCT_DEV_CORE_OK) {
3971f21fb3edSRaghu Vatsavayi 		schedule_delayed_work(&oct->nic_poll_work.work,
3972f21fb3edSRaghu Vatsavayi 				      LIQUIDIO_STARTER_POLL_INTERVAL_MS);
3973f21fb3edSRaghu Vatsavayi 		return;
3974f21fb3edSRaghu Vatsavayi 	}
3975f21fb3edSRaghu Vatsavayi 
3976f21fb3edSRaghu Vatsavayi 	atomic_set(&oct->status, OCT_DEV_RUNNING);
3977f21fb3edSRaghu Vatsavayi 
3978f21fb3edSRaghu Vatsavayi 	if (oct->app_mode && oct->app_mode == CVM_DRV_NIC_APP) {
3979f21fb3edSRaghu Vatsavayi 		dev_dbg(&oct->pci_dev->dev, "Starting NIC module\n");
3980f21fb3edSRaghu Vatsavayi 
3981f21fb3edSRaghu Vatsavayi 		if (liquidio_init_nic_module(oct))
3982f21fb3edSRaghu Vatsavayi 			dev_err(&oct->pci_dev->dev, "NIC initialization failed\n");
3983f21fb3edSRaghu Vatsavayi 		else
3984f21fb3edSRaghu Vatsavayi 			handshake[oct->octeon_id].started_ok = 1;
3985f21fb3edSRaghu Vatsavayi 	} else {
3986f21fb3edSRaghu Vatsavayi 		dev_err(&oct->pci_dev->dev,
3987f21fb3edSRaghu Vatsavayi 			"Unexpected application running on NIC (%d). Check firmware.\n",
3988f21fb3edSRaghu Vatsavayi 			oct->app_mode);
3989f21fb3edSRaghu Vatsavayi 	}
3990f21fb3edSRaghu Vatsavayi 
3991f21fb3edSRaghu Vatsavayi 	complete(&handshake[oct->octeon_id].started);
3992f21fb3edSRaghu Vatsavayi }
3993f21fb3edSRaghu Vatsavayi 
3994f21fb3edSRaghu Vatsavayi static int
octeon_recv_vf_drv_notice(struct octeon_recv_info * recv_info,void * buf)3995f21fb3edSRaghu Vatsavayi octeon_recv_vf_drv_notice(struct octeon_recv_info *recv_info, void *buf)
3996f21fb3edSRaghu Vatsavayi {
3997f21fb3edSRaghu Vatsavayi 	struct octeon_device *oct = (struct octeon_device *)buf;
3998f21fb3edSRaghu Vatsavayi 	struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
399986dea55bSRaghu Vatsavayi 	int i, notice, vf_idx;
400086dea55bSRaghu Vatsavayi 	bool cores_crashed;
400186dea55bSRaghu Vatsavayi 	u64 *data, vf_num;
400286dea55bSRaghu Vatsavayi 
400386dea55bSRaghu Vatsavayi 	notice = recv_pkt->rh.r.ossp;
400486dea55bSRaghu Vatsavayi 	data = (u64 *)(get_rbd(recv_pkt->buffer_ptr[0]) + OCT_DROQ_INFO_SIZE);
4005bb54be58SFelix Manlunas 
400686dea55bSRaghu Vatsavayi 	/* the first 64-bit word of data is the vf_num */
400786dea55bSRaghu Vatsavayi 	vf_num = data[0];
400886dea55bSRaghu Vatsavayi 	octeon_swap_8B_data(&vf_num, 1);
4009c4ee5d81SPrasad Kanneganti 	vf_idx = (int)vf_num - 1;
401086dea55bSRaghu Vatsavayi 
401186dea55bSRaghu Vatsavayi 	cores_crashed = READ_ONCE(oct->cores_crashed);
401286dea55bSRaghu Vatsavayi 
401386dea55bSRaghu Vatsavayi 	if (notice == VF_DRV_LOADED) {
401486dea55bSRaghu Vatsavayi 		if (!(oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vf_idx))) {
401586dea55bSRaghu Vatsavayi 			oct->sriov_info.vf_drv_loaded_mask |= BIT_ULL(vf_idx);
4016bb54be58SFelix Manlunas 			dev_info(&oct->pci_dev->dev,
4017bb54be58SFelix Manlunas 				 "driver for VF%d was loaded\n", vf_idx);
401886dea55bSRaghu Vatsavayi 			if (!cores_crashed)
401986dea55bSRaghu Vatsavayi 				try_module_get(THIS_MODULE);
402086dea55bSRaghu Vatsavayi 		}
402186dea55bSRaghu Vatsavayi 	} else if (notice == VF_DRV_REMOVED) {
402286dea55bSRaghu Vatsavayi 		if (oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vf_idx)) {
4023bb54be58SFelix Manlunas 			oct->sriov_info.vf_drv_loaded_mask &= ~BIT_ULL(vf_idx);
402486dea55bSRaghu Vatsavayi 			dev_info(&oct->pci_dev->dev,
402586dea55bSRaghu Vatsavayi 				 "driver for VF%d was removed\n", vf_idx);
402686dea55bSRaghu Vatsavayi 			if (!cores_crashed)
402786dea55bSRaghu Vatsavayi 				module_put(THIS_MODULE);
402886dea55bSRaghu Vatsavayi 		}
402986dea55bSRaghu Vatsavayi 	} else if (notice == VF_DRV_MACADDR_CHANGED) {
403086dea55bSRaghu Vatsavayi 		u8 *b = (u8 *)&data[1];
4031bb54be58SFelix Manlunas 
403286dea55bSRaghu Vatsavayi 		oct->sriov_info.vf_macaddr[vf_idx] = data[1];
403386dea55bSRaghu Vatsavayi 		dev_info(&oct->pci_dev->dev,
403486dea55bSRaghu Vatsavayi 			 "VF driver changed VF%d's MAC address to %pM\n",
403586dea55bSRaghu Vatsavayi 			 vf_idx, b + 2);
403686dea55bSRaghu Vatsavayi 	}
403786dea55bSRaghu Vatsavayi 
403886dea55bSRaghu Vatsavayi 	for (i = 0; i < recv_pkt->buffer_count; i++)
403986dea55bSRaghu Vatsavayi 		recv_buffer_free(recv_pkt->buffer_ptr[i]);
404086dea55bSRaghu Vatsavayi 	octeon_free_recv_info(recv_info);
404186dea55bSRaghu Vatsavayi 
404286dea55bSRaghu Vatsavayi 	return 0;
404386dea55bSRaghu Vatsavayi }
404486dea55bSRaghu Vatsavayi 
404586dea55bSRaghu Vatsavayi /**
404686dea55bSRaghu Vatsavayi  * octeon_device_init - Device initialization for each Octeon device that is probed
404786dea55bSRaghu Vatsavayi  * @octeon_dev:  octeon device
404886dea55bSRaghu Vatsavayi  */
octeon_device_init(struct octeon_device * octeon_dev)404986dea55bSRaghu Vatsavayi static int octeon_device_init(struct octeon_device *octeon_dev)
4050f21fb3edSRaghu Vatsavayi {
4051d0ea5cbdSJesse Brandeburg 	int j, ret;
4052d0ea5cbdSJesse Brandeburg 	char bootcmd[] = "\n";
4053f21fb3edSRaghu Vatsavayi 	char *dbg_enb = NULL;
4054f21fb3edSRaghu Vatsavayi 	enum lio_fw_state fw_state;
4055f21fb3edSRaghu Vatsavayi 	struct octeon_device_priv *oct_priv = octeon_dev->priv;
4056f21fb3edSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE);
4057d3d7e6c6SRaghu Vatsavayi 
4058da1542b0SRick Farrington 	/* Enable access to the octeon device and make its DMA capability
4059088b8749SRick Farrington 	 * known to the OS.
4060f21fb3edSRaghu Vatsavayi 	 */
4061f21fb3edSRaghu Vatsavayi 	if (octeon_pci_os_setup(octeon_dev))
4062f21fb3edSRaghu Vatsavayi 		return 1;
4063f21fb3edSRaghu Vatsavayi 
4064f21fb3edSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_PCI_ENABLE_DONE);
4065f21fb3edSRaghu Vatsavayi 
4066f21fb3edSRaghu Vatsavayi 	/* Identify the Octeon type and map the BAR address space. */
4067f21fb3edSRaghu Vatsavayi 	if (octeon_chip_specific_setup(octeon_dev)) {
4068f21fb3edSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev, "Chip specific setup failed\n");
4069f21fb3edSRaghu Vatsavayi 		return 1;
4070515e752dSRaghu Vatsavayi 	}
4071515e752dSRaghu Vatsavayi 
4072f21fb3edSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_PCI_MAP_DONE);
4073f21fb3edSRaghu Vatsavayi 
4074f21fb3edSRaghu Vatsavayi 	/* Only add a reference after setting status 'OCT_DEV_PCI_MAP_DONE',
4075f21fb3edSRaghu Vatsavayi 	 * since that is what is required for the reference to be removed
4076f21fb3edSRaghu Vatsavayi 	 * during de-initialization (see 'octeon_destroy_resources').
4077f21fb3edSRaghu Vatsavayi 	 */
4078f21fb3edSRaghu Vatsavayi 	octeon_register_device(octeon_dev, octeon_dev->pci_dev->bus->number,
4079f21fb3edSRaghu Vatsavayi 			       PCI_SLOT(octeon_dev->pci_dev->devfn),
4080e1e3ce62SRick Farrington 			       PCI_FUNC(octeon_dev->pci_dev->devfn),
4081e1e3ce62SRick Farrington 			       true);
4082e1e3ce62SRick Farrington 
4083e1e3ce62SRick Farrington 	octeon_dev->app_mode = CVM_DRV_INVALID_APP;
4084e1e3ce62SRick Farrington 
4085e1e3ce62SRick Farrington 	/* CN23XX supports preloaded firmware if the following is true:
4086e1e3ce62SRick Farrington 	 *
4087e1e3ce62SRick Farrington 	 * The adapter indicates that firmware is currently running AND
4088e1e3ce62SRick Farrington 	 * 'fw_type' is 'auto'.
4089f21fb3edSRaghu Vatsavayi 	 *
4090f21fb3edSRaghu Vatsavayi 	 * (default state is NEEDS_TO_BE_LOADED, override it if appropriate).
4091088b8749SRick Farrington 	 */
4092088b8749SRick Farrington 	if (OCTEON_CN23XX_PF(octeon_dev) &&
4093088b8749SRick Farrington 	    cn23xx_fw_loaded(octeon_dev) && fw_type_is_auto()) {
4094088b8749SRick Farrington 		atomic_cmpxchg(octeon_dev->adapter_fw_state,
4095088b8749SRick Farrington 			       FW_NEEDS_TO_BE_LOADED, FW_IS_PRELOADED);
4096088b8749SRick Farrington 	}
4097088b8749SRick Farrington 
4098088b8749SRick Farrington 	/* If loading firmware, only first device of adapter needs to do so. */
4099088b8749SRick Farrington 	fw_state = atomic_cmpxchg(octeon_dev->adapter_fw_state,
4100088b8749SRick Farrington 				  FW_NEEDS_TO_BE_LOADED,
4101088b8749SRick Farrington 				  FW_IS_BEING_LOADED);
4102088b8749SRick Farrington 
4103088b8749SRick Farrington 	/* Here, [local variable] 'fw_state' is set to one of:
4104088b8749SRick Farrington 	 *
4105088b8749SRick Farrington 	 *   FW_IS_PRELOADED:       No firmware is to be loaded (see above)
4106088b8749SRick Farrington 	 *   FW_NEEDS_TO_BE_LOADED: The driver's first instance will load
4107088b8749SRick Farrington 	 *                          firmware to the adapter.
4108088b8749SRick Farrington 	 *   FW_IS_BEING_LOADED:    The driver's second instance will not load
4109088b8749SRick Farrington 	 *                          firmware to the adapter.
4110088b8749SRick Farrington 	 */
4111088b8749SRick Farrington 
4112088b8749SRick Farrington 	/* Prior to f/w load, perform a soft reset of the Octeon device;
4113088b8749SRick Farrington 	 * if error resetting, return w/error.
4114088b8749SRick Farrington 	 */
4115088b8749SRick Farrington 	if (fw_state == FW_NEEDS_TO_BE_LOADED)
4116088b8749SRick Farrington 		if (octeon_dev->fn_list.soft_reset(octeon_dev))
4117088b8749SRick Farrington 			return 1;
4118088b8749SRick Farrington 
4119088b8749SRick Farrington 	/* Initialize the dispatch mechanism used to push packets arriving on
4120088b8749SRick Farrington 	 * Octeon Output queues.
4121088b8749SRick Farrington 	 */
4122f21fb3edSRaghu Vatsavayi 	if (octeon_init_dispatch_list(octeon_dev))
4123f21fb3edSRaghu Vatsavayi 		return 1;
4124f21fb3edSRaghu Vatsavayi 
4125f21fb3edSRaghu Vatsavayi 	octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC,
4126f21fb3edSRaghu Vatsavayi 				    OPCODE_NIC_CORE_DRV_ACTIVE,
4127f21fb3edSRaghu Vatsavayi 				    octeon_core_drv_init,
4128f21fb3edSRaghu Vatsavayi 				    octeon_dev);
4129f21fb3edSRaghu Vatsavayi 
4130f21fb3edSRaghu Vatsavayi 	octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC,
4131f21fb3edSRaghu Vatsavayi 				    OPCODE_NIC_VF_DRV_NOTICE,
4132f21fb3edSRaghu Vatsavayi 				    octeon_recv_vf_drv_notice, octeon_dev);
4133f21fb3edSRaghu Vatsavayi 	INIT_DELAYED_WORK(&octeon_dev->nic_poll_work.work, nic_starter);
4134f21fb3edSRaghu Vatsavayi 	octeon_dev->nic_poll_work.ctxptr = (void *)octeon_dev;
4135f21fb3edSRaghu Vatsavayi 	schedule_delayed_work(&octeon_dev->nic_poll_work.work,
413686dea55bSRaghu Vatsavayi 			      LIQUIDIO_STARTER_POLL_INTERVAL_MS);
413786dea55bSRaghu Vatsavayi 
413886dea55bSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_DISPATCH_INIT_DONE);
4139f21fb3edSRaghu Vatsavayi 
4140f21fb3edSRaghu Vatsavayi 	if (octeon_set_io_queues_off(octeon_dev)) {
4141f21fb3edSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev, "setting io queues off failed\n");
4142f21fb3edSRaghu Vatsavayi 		return 1;
4143f21fb3edSRaghu Vatsavayi 	}
4144f21fb3edSRaghu Vatsavayi 
4145f21fb3edSRaghu Vatsavayi 	if (OCTEON_CN23XX_PF(octeon_dev)) {
4146c865cdf1SRaghu Vatsavayi 		ret = octeon_dev->fn_list.setup_device_regs(octeon_dev);
4147c865cdf1SRaghu Vatsavayi 		if (ret) {
4148c865cdf1SRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "OCTEON: Failed to configure device registers\n");
4149c865cdf1SRaghu Vatsavayi 			return ret;
4150f21fb3edSRaghu Vatsavayi 		}
41513451b97cSRaghu Vatsavayi 	}
41523451b97cSRaghu Vatsavayi 
41533451b97cSRaghu Vatsavayi 	/* Initialize soft command buffer pool
41543451b97cSRaghu Vatsavayi 	 */
41553451b97cSRaghu Vatsavayi 	if (octeon_setup_sc_buffer_pool(octeon_dev)) {
41563451b97cSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev, "sc buffer pool allocation failed\n");
41573451b97cSRaghu Vatsavayi 		return 1;
41583451b97cSRaghu Vatsavayi 	}
41593451b97cSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_SC_BUFF_POOL_INIT_DONE);
41603451b97cSRaghu Vatsavayi 
41613451b97cSRaghu Vatsavayi 	/*  Setup the data structures that manage this Octeon's Input queues. */
41623451b97cSRaghu Vatsavayi 	if (octeon_setup_instr_queues(octeon_dev)) {
41633451b97cSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev,
41643451b97cSRaghu Vatsavayi 			"instruction queue initialization failed\n");
41653451b97cSRaghu Vatsavayi 		return 1;
41663451b97cSRaghu Vatsavayi 	}
4167f21fb3edSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_INSTR_QUEUE_INIT_DONE);
4168f21fb3edSRaghu Vatsavayi 
4169f21fb3edSRaghu Vatsavayi 	/* Initialize lists to manage the requests of different types that
4170f21fb3edSRaghu Vatsavayi 	 * arrive from user & kernel applications for this octeon device.
4171f21fb3edSRaghu Vatsavayi 	 */
4172f21fb3edSRaghu Vatsavayi 	if (octeon_setup_response_list(octeon_dev)) {
4173f21fb3edSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev, "Response list allocation failed\n");
4174f21fb3edSRaghu Vatsavayi 		return 1;
4175f21fb3edSRaghu Vatsavayi 	}
4176f21fb3edSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_RESP_LIST_INIT_DONE);
4177f21fb3edSRaghu Vatsavayi 
4178f21fb3edSRaghu Vatsavayi 	if (octeon_setup_output_queues(octeon_dev)) {
4179f21fb3edSRaghu Vatsavayi 		dev_err(&octeon_dev->pci_dev->dev, "Output queue initialization failed\n");
4180f21fb3edSRaghu Vatsavayi 		return 1;
4181f21fb3edSRaghu Vatsavayi 	}
4182f21fb3edSRaghu Vatsavayi 
4183f21fb3edSRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_DROQ_INIT_DONE);
4184f21fb3edSRaghu Vatsavayi 
4185f21fb3edSRaghu Vatsavayi 	if (OCTEON_CN23XX_PF(octeon_dev)) {
41861e0d30feSRaghu Vatsavayi 		if (octeon_dev->fn_list.setup_mbox(octeon_dev)) {
4187f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "OCTEON: Mailbox setup failed\n");
4188f21fb3edSRaghu Vatsavayi 			return 1;
4189f21fb3edSRaghu Vatsavayi 		}
4190f21fb3edSRaghu Vatsavayi 		atomic_set(&octeon_dev->status, OCT_DEV_MBOX_SETUP_DONE);
41915b07aee1SRaghu Vatsavayi 
41925d65556bSRaghu Vatsavayi 		if (octeon_allocate_ioq_vector
41935d65556bSRaghu Vatsavayi 				(octeon_dev,
41945d65556bSRaghu Vatsavayi 				 octeon_dev->sriov_info.num_pf_rings)) {
41955d65556bSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "OCTEON: ioq vector allocation failed\n");
41965d65556bSRaghu Vatsavayi 			return 1;
41975d65556bSRaghu Vatsavayi 		}
4198c33c9973SIntiyaz Basha 		atomic_set(&octeon_dev->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE);
4199c33c9973SIntiyaz Basha 
4200c33c9973SIntiyaz Basha 	} else {
42015b07aee1SRaghu Vatsavayi 		/* The input and output queue registers were setup earlier (the
42025b07aee1SRaghu Vatsavayi 		 * queues were not enabled). Any additional registers
42035b07aee1SRaghu Vatsavayi 		 * that need to be programmed should be done now.
4204515e752dSRaghu Vatsavayi 		 */
42055b07aee1SRaghu Vatsavayi 		ret = octeon_dev->fn_list.setup_device_regs(octeon_dev);
42065b07aee1SRaghu Vatsavayi 		if (ret) {
42075b07aee1SRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev,
42085b07aee1SRaghu Vatsavayi 				"Failed to configure device registers\n");
42095b07aee1SRaghu Vatsavayi 			return ret;
4210f21fb3edSRaghu Vatsavayi 		}
4211f21fb3edSRaghu Vatsavayi 	}
4212f21fb3edSRaghu Vatsavayi 
4213f21fb3edSRaghu Vatsavayi 	/* Initialize the tasklet that handles output queue packet processing.*/
4214f21fb3edSRaghu Vatsavayi 	dev_dbg(&octeon_dev->pci_dev->dev, "Initializing droq tasklet\n");
4215f21fb3edSRaghu Vatsavayi 	tasklet_setup(&oct_priv->droq_tasklet, octeon_droq_bh);
4216f21fb3edSRaghu Vatsavayi 
42175b07aee1SRaghu Vatsavayi 	/* Setup the interrupt handler and record the INT SUM register address
4218f21fb3edSRaghu Vatsavayi 	 */
4219f21fb3edSRaghu Vatsavayi 	if (octeon_setup_interrupt(octeon_dev,
4220f21fb3edSRaghu Vatsavayi 				   octeon_dev->sriov_info.num_pf_rings))
4221dfe4e612SAllen Pais 		return 1;
4222f21fb3edSRaghu Vatsavayi 
4223f21fb3edSRaghu Vatsavayi 	/* Enable Octeon device interrupts */
4224f21fb3edSRaghu Vatsavayi 	octeon_dev->fn_list.enable_interrupt(octeon_dev, OCTEON_ALL_INTR);
4225a82457f1SIntiyaz Basha 
4226a82457f1SIntiyaz Basha 	atomic_set(&octeon_dev->status, OCT_DEV_INTR_SET_DONE);
42271e0d30feSRaghu Vatsavayi 
4228f21fb3edSRaghu Vatsavayi 	/* Send Credit for Octeon Output queues. Credits are always sent BEFORE
4229f21fb3edSRaghu Vatsavayi 	 * the output queue is enabled.
42305b07aee1SRaghu Vatsavayi 	 * This ensures that we'll receive the f/w CORE DRV_ACTIVE message in
4231f21fb3edSRaghu Vatsavayi 	 * case we've configured CN23XX_SLI_GBL_CONTROL[NOPTR_D] = 0.
4232515e752dSRaghu Vatsavayi 	 * Otherwise, it is possible that the DRV_ACTIVE message will be sent
4233515e752dSRaghu Vatsavayi 	 * before any credits have been issued, causing the ring to be reset
42343c57f615SRick Farrington 	 * (and the f/w appear to never have started).
42353c57f615SRick Farrington 	 */
42363c57f615SRick Farrington 	for (j = 0; j < octeon_dev->num_oqs; j++)
42373c57f615SRick Farrington 		writel(octeon_dev->droq[j]->max_count,
42383c57f615SRick Farrington 		       octeon_dev->droq[j]->pkts_credit_reg);
42393c57f615SRick Farrington 
42403c57f615SRick Farrington 	/* Enable the input and output queues for this Octeon device */
42413c57f615SRick Farrington 	ret = octeon_dev->fn_list.enable_io_queues(octeon_dev);
42423c57f615SRick Farrington 	if (ret) {
42433c57f615SRick Farrington 		dev_err(&octeon_dev->pci_dev->dev, "Failed to enable input/output queues");
42443c57f615SRick Farrington 		return ret;
42453c57f615SRick Farrington 	}
4246f21fb3edSRaghu Vatsavayi 
42471b7c55c4SRaghu Vatsavayi 	atomic_set(&octeon_dev->status, OCT_DEV_IO_QUEUES_DONE);
42481b7c55c4SRaghu Vatsavayi 
42491b7c55c4SRaghu Vatsavayi 	if (fw_state == FW_NEEDS_TO_BE_LOADED) {
42501b7c55c4SRaghu Vatsavayi 		dev_dbg(&octeon_dev->pci_dev->dev, "Waiting for DDR initialization...\n");
42511b7c55c4SRaghu Vatsavayi 		if (!ddr_timeout) {
4252f21fb3edSRaghu Vatsavayi 			dev_info(&octeon_dev->pci_dev->dev,
4253f21fb3edSRaghu Vatsavayi 				 "WAITING. Set ddr_timeout to non-zero value to proceed with initialization.\n");
4254f21fb3edSRaghu Vatsavayi 		}
4255088b8749SRick Farrington 
4256f21fb3edSRaghu Vatsavayi 		schedule_timeout_uninterruptible(HZ * LIO_RESET_SECS);
4257c0eab5b3SRaghu Vatsavayi 
4258c0eab5b3SRaghu Vatsavayi 		/* Wait for the octeon to initialize DDR after the soft-reset.*/
4259c0eab5b3SRaghu Vatsavayi 		while (!ddr_timeout) {
4260c0eab5b3SRaghu Vatsavayi 			set_current_state(TASK_INTERRUPTIBLE);
4261f21fb3edSRaghu Vatsavayi 			if (schedule_timeout(HZ / 10)) {
4262f21fb3edSRaghu Vatsavayi 				/* user probably pressed Control-C */
4263f21fb3edSRaghu Vatsavayi 				return 1;
4264f21fb3edSRaghu Vatsavayi 			}
4265c0eab5b3SRaghu Vatsavayi 		}
42664b129ae3SRaghu Vatsavayi 		ret = octeon_wait_for_ddr_init(octeon_dev, &ddr_timeout);
42674b129ae3SRaghu Vatsavayi 		if (ret) {
42684b129ae3SRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev,
42694b129ae3SRaghu Vatsavayi 				"DDR not initialized. Please confirm that board is configured to boot from Flash, ret: %d\n",
42704b129ae3SRaghu Vatsavayi 				ret);
42714b129ae3SRaghu Vatsavayi 			return 1;
4272f21fb3edSRaghu Vatsavayi 		}
4273f21fb3edSRaghu Vatsavayi 
4274f21fb3edSRaghu Vatsavayi 		if (octeon_wait_for_bootloader(octeon_dev, 1000)) {
4275f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "Board not responding\n");
4276f21fb3edSRaghu Vatsavayi 			return 1;
4277f21fb3edSRaghu Vatsavayi 		}
4278f21fb3edSRaghu Vatsavayi 
4279f21fb3edSRaghu Vatsavayi 		/* Divert uboot to take commands from host instead. */
4280c0eab5b3SRaghu Vatsavayi 		ret = octeon_console_send_cmd(octeon_dev, bootcmd, 50);
4281f21fb3edSRaghu Vatsavayi 
4282f21fb3edSRaghu Vatsavayi 		dev_dbg(&octeon_dev->pci_dev->dev, "Initializing consoles\n");
4283f21fb3edSRaghu Vatsavayi 		ret = octeon_init_consoles(octeon_dev);
4284f21fb3edSRaghu Vatsavayi 		if (ret) {
4285d3d7e6c6SRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "Could not access board consoles\n");
4286d3d7e6c6SRaghu Vatsavayi 			return 1;
4287d3d7e6c6SRaghu Vatsavayi 		}
4288f21fb3edSRaghu Vatsavayi 		/* If console debug enabled, specify empty string to use default
4289f21fb3edSRaghu Vatsavayi 		 * enablement ELSE specify NULL string for 'disabled'.
4290f21fb3edSRaghu Vatsavayi 		 */
4291f21fb3edSRaghu Vatsavayi 		dbg_enb = octeon_console_debug_enabled(0) ? "" : NULL;
4292f21fb3edSRaghu Vatsavayi 		ret = octeon_add_console(octeon_dev, 0, dbg_enb);
4293f21fb3edSRaghu Vatsavayi 		if (ret) {
4294da1542b0SRick Farrington 			dev_err(&octeon_dev->pci_dev->dev, "Could not access board console\n");
4295da1542b0SRick Farrington 			return 1;
4296da1542b0SRick Farrington 		} else if (octeon_console_debug_enabled(0)) {
4297da1542b0SRick Farrington 			/* If console was added AND we're logging console output
4298da1542b0SRick Farrington 			 * then set our console print function.
4299f21fb3edSRaghu Vatsavayi 			 */
4300f21fb3edSRaghu Vatsavayi 			octeon_dev->console[0].print = octeon_dbg_console_print;
4301f21fb3edSRaghu Vatsavayi 		}
4302da1542b0SRick Farrington 
4303da1542b0SRick Farrington 		atomic_set(&octeon_dev->status, OCT_DEV_CONSOLE_INIT_DONE);
4304da1542b0SRick Farrington 
4305da1542b0SRick Farrington 		dev_dbg(&octeon_dev->pci_dev->dev, "Loading firmware\n");
4306da1542b0SRick Farrington 		ret = load_firmware(octeon_dev);
4307f21fb3edSRaghu Vatsavayi 		if (ret) {
4308f21fb3edSRaghu Vatsavayi 			dev_err(&octeon_dev->pci_dev->dev, "Could not load firmware to board\n");
4309f21fb3edSRaghu Vatsavayi 			return 1;
4310f21fb3edSRaghu Vatsavayi 		}
4311f21fb3edSRaghu Vatsavayi 
4312f21fb3edSRaghu Vatsavayi 		atomic_set(octeon_dev->adapter_fw_state, FW_HAS_BEEN_LOADED);
4313f21fb3edSRaghu Vatsavayi 	}
4314f21fb3edSRaghu Vatsavayi 
4315f21fb3edSRaghu Vatsavayi 	handshake[octeon_dev->octeon_id].init_ok = 1;
4316f21fb3edSRaghu Vatsavayi 	complete(&handshake[octeon_dev->octeon_id].init);
4317088b8749SRick Farrington 
4318088b8749SRick Farrington 	atomic_set(&octeon_dev->status, OCT_DEV_HOST_OK);
4319c0eab5b3SRaghu Vatsavayi 	oct_priv->dev = octeon_dev;
4320f21fb3edSRaghu Vatsavayi 
4321f21fb3edSRaghu Vatsavayi 	return 0;
4322f21fb3edSRaghu Vatsavayi }
4323f21fb3edSRaghu Vatsavayi 
4324f21fb3edSRaghu Vatsavayi /**
4325dfe4e612SAllen Pais  * octeon_dbg_console_print - Debug console print function
4326f21fb3edSRaghu Vatsavayi  * @oct:  octeon device
4327f21fb3edSRaghu Vatsavayi  * @console_num: console number
4328f21fb3edSRaghu Vatsavayi  * @prefix:      first portion of line to display
4329f21fb3edSRaghu Vatsavayi  * @suffix:      second portion of line to display
4330f21fb3edSRaghu Vatsavayi  *
4331d0ea5cbdSJesse Brandeburg  * The OCTEON debug console outputs entire lines (excluding '\n').
4332d0ea5cbdSJesse Brandeburg  * Normally, the line will be passed in the 'prefix' parameter.
4333d0ea5cbdSJesse Brandeburg  * However, due to buffering, it is possible for a line to be split into two
4334d0ea5cbdSJesse Brandeburg  * parts, in which case they will be passed as the 'prefix' parameter and
4335d0ea5cbdSJesse Brandeburg  * 'suffix' parameter.
4336da1542b0SRick Farrington  */
octeon_dbg_console_print(struct octeon_device * oct,u32 console_num,char * prefix,char * suffix)4337da1542b0SRick Farrington static int octeon_dbg_console_print(struct octeon_device *oct, u32 console_num,
4338da1542b0SRick Farrington 				    char *prefix, char *suffix)
4339da1542b0SRick Farrington {
4340da1542b0SRick Farrington 	if (prefix && suffix)
4341da1542b0SRick Farrington 		dev_info(&oct->pci_dev->dev, "%u: %s%s\n", console_num, prefix,
4342da1542b0SRick Farrington 			 suffix);
4343da1542b0SRick Farrington 	else if (prefix)
4344da1542b0SRick Farrington 		dev_info(&oct->pci_dev->dev, "%u: %s\n", console_num, prefix);
4345da1542b0SRick Farrington 	else if (suffix)
4346da1542b0SRick Farrington 		dev_info(&oct->pci_dev->dev, "%u: %s\n", console_num, suffix);
4347da1542b0SRick Farrington 
4348da1542b0SRick Farrington 	return 0;
4349da1542b0SRick Farrington }
4350da1542b0SRick Farrington 
4351da1542b0SRick Farrington /**
4352da1542b0SRick Farrington  * liquidio_exit - Exits the module
4353da1542b0SRick Farrington  */
liquidio_exit(void)4354da1542b0SRick Farrington static void __exit liquidio_exit(void)
4355da1542b0SRick Farrington {
4356da1542b0SRick Farrington 	liquidio_deinit_pci();
4357da1542b0SRick Farrington 
4358d0ea5cbdSJesse Brandeburg 	pr_info("LiquidIO network module is now unloaded\n");
4359f21fb3edSRaghu Vatsavayi }
4360f21fb3edSRaghu Vatsavayi 
4361f21fb3edSRaghu Vatsavayi module_init(liquidio_init);
4362f21fb3edSRaghu Vatsavayi module_exit(liquidio_exit);
4363f21fb3edSRaghu Vatsavayi