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, µ) != 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