xref: /dpdk/drivers/net/ionic/ionic_ethdev.c (revision a27d9013)
17c125393SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
27c125393SAlfredo Cardigliano  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
37c125393SAlfredo Cardigliano  */
47c125393SAlfredo Cardigliano 
55ef51809SAlfredo Cardigliano #include <rte_pci.h>
65ef51809SAlfredo Cardigliano #include <rte_bus_pci.h>
75ef51809SAlfredo Cardigliano #include <rte_ethdev.h>
85ef51809SAlfredo Cardigliano #include <rte_ethdev_driver.h>
95ef51809SAlfredo Cardigliano #include <rte_malloc.h>
10669c8de6SAlfredo Cardigliano #include <rte_ethdev_pci.h>
115ef51809SAlfredo Cardigliano 
127c125393SAlfredo Cardigliano #include "ionic_logs.h"
135ef51809SAlfredo Cardigliano #include "ionic.h"
145ef51809SAlfredo Cardigliano #include "ionic_dev.h"
155ef51809SAlfredo Cardigliano #include "ionic_mac_api.h"
16669c8de6SAlfredo Cardigliano #include "ionic_lif.h"
17669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h"
18*a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h"
19669c8de6SAlfredo Cardigliano 
20669c8de6SAlfredo Cardigliano static int  eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params);
21669c8de6SAlfredo Cardigliano static int  eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev);
22598f6726SAlfredo Cardigliano static int  ionic_dev_info_get(struct rte_eth_dev *eth_dev,
23598f6726SAlfredo Cardigliano 	struct rte_eth_dev_info *dev_info);
24598f6726SAlfredo Cardigliano static int  ionic_dev_configure(struct rte_eth_dev *dev);
25598f6726SAlfredo Cardigliano static int  ionic_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
26598f6726SAlfredo Cardigliano static int  ionic_dev_start(struct rte_eth_dev *dev);
27598f6726SAlfredo Cardigliano static void ionic_dev_stop(struct rte_eth_dev *dev);
28598f6726SAlfredo Cardigliano static void ionic_dev_close(struct rte_eth_dev *dev);
29598f6726SAlfredo Cardigliano static int  ionic_dev_set_link_up(struct rte_eth_dev *dev);
30598f6726SAlfredo Cardigliano static int  ionic_dev_set_link_down(struct rte_eth_dev *dev);
31598f6726SAlfredo Cardigliano static int  ionic_dev_link_update(struct rte_eth_dev *eth_dev,
32598f6726SAlfredo Cardigliano 	int wait_to_complete);
33ec15c66bSAlfredo Cardigliano static int  ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev,
34ec15c66bSAlfredo Cardigliano 	struct rte_eth_fc_conf *fc_conf);
35ec15c66bSAlfredo Cardigliano static int  ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev,
36ec15c66bSAlfredo Cardigliano 	struct rte_eth_fc_conf *fc_conf);
37*a27d9013SAlfredo Cardigliano static int  ionic_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask);
387c125393SAlfredo Cardigliano 
397c125393SAlfredo Cardigliano int ionic_logtype;
407c125393SAlfredo Cardigliano 
415ef51809SAlfredo Cardigliano static const struct rte_pci_id pci_id_ionic_map[] = {
425ef51809SAlfredo Cardigliano 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) },
435ef51809SAlfredo Cardigliano 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) },
445ef51809SAlfredo Cardigliano 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) },
455ef51809SAlfredo Cardigliano 	{ .vendor_id = 0, /* sentinel */ },
465ef51809SAlfredo Cardigliano };
475ef51809SAlfredo Cardigliano 
48*a27d9013SAlfredo Cardigliano static const struct rte_eth_desc_lim rx_desc_lim = {
49*a27d9013SAlfredo Cardigliano 	.nb_max = IONIC_MAX_RING_DESC,
50*a27d9013SAlfredo Cardigliano 	.nb_min = IONIC_MIN_RING_DESC,
51*a27d9013SAlfredo Cardigliano 	.nb_align = 1,
52*a27d9013SAlfredo Cardigliano };
53*a27d9013SAlfredo Cardigliano 
54*a27d9013SAlfredo Cardigliano static const struct rte_eth_desc_lim tx_desc_lim = {
55*a27d9013SAlfredo Cardigliano 	.nb_max = IONIC_MAX_RING_DESC,
56*a27d9013SAlfredo Cardigliano 	.nb_min = IONIC_MIN_RING_DESC,
57*a27d9013SAlfredo Cardigliano 	.nb_align = 1,
58*a27d9013SAlfredo Cardigliano 	.nb_seg_max = IONIC_TX_MAX_SG_ELEMS,
59*a27d9013SAlfredo Cardigliano 	.nb_mtu_seg_max = IONIC_TX_MAX_SG_ELEMS,
60*a27d9013SAlfredo Cardigliano };
61*a27d9013SAlfredo Cardigliano 
62669c8de6SAlfredo Cardigliano static const struct eth_dev_ops ionic_eth_dev_ops = {
63598f6726SAlfredo Cardigliano 	.dev_infos_get          = ionic_dev_info_get,
64598f6726SAlfredo Cardigliano 	.dev_configure          = ionic_dev_configure,
65598f6726SAlfredo Cardigliano 	.mtu_set                = ionic_dev_mtu_set,
66598f6726SAlfredo Cardigliano 	.dev_start              = ionic_dev_start,
67598f6726SAlfredo Cardigliano 	.dev_stop               = ionic_dev_stop,
68598f6726SAlfredo Cardigliano 	.dev_close              = ionic_dev_close,
69598f6726SAlfredo Cardigliano 	.link_update            = ionic_dev_link_update,
70598f6726SAlfredo Cardigliano 	.dev_set_link_up        = ionic_dev_set_link_up,
71598f6726SAlfredo Cardigliano 	.dev_set_link_down      = ionic_dev_set_link_down,
7254fe083fSAlfredo Cardigliano 	.mac_addr_add           = ionic_dev_add_mac,
7354fe083fSAlfredo Cardigliano 	.mac_addr_remove        = ionic_dev_remove_mac,
7454fe083fSAlfredo Cardigliano 	.mac_addr_set           = ionic_dev_set_mac,
7554fe083fSAlfredo Cardigliano 	.vlan_filter_set        = ionic_dev_vlan_filter_set,
7654fe083fSAlfredo Cardigliano 	.promiscuous_enable     = ionic_dev_promiscuous_enable,
7754fe083fSAlfredo Cardigliano 	.promiscuous_disable    = ionic_dev_promiscuous_disable,
7854fe083fSAlfredo Cardigliano 	.allmulticast_enable    = ionic_dev_allmulticast_enable,
7954fe083fSAlfredo Cardigliano 	.allmulticast_disable   = ionic_dev_allmulticast_disable,
80ec15c66bSAlfredo Cardigliano 	.flow_ctrl_get          = ionic_flow_ctrl_get,
81ec15c66bSAlfredo Cardigliano 	.flow_ctrl_set          = ionic_flow_ctrl_set,
82*a27d9013SAlfredo Cardigliano 	.rxq_info_get           = ionic_rxq_info_get,
83*a27d9013SAlfredo Cardigliano 	.txq_info_get           = ionic_txq_info_get,
84*a27d9013SAlfredo Cardigliano 	.rx_queue_setup         = ionic_dev_rx_queue_setup,
85*a27d9013SAlfredo Cardigliano 	.rx_queue_release       = ionic_dev_rx_queue_release,
86*a27d9013SAlfredo Cardigliano 	.rx_queue_start	        = ionic_dev_rx_queue_start,
87*a27d9013SAlfredo Cardigliano 	.rx_queue_stop          = ionic_dev_rx_queue_stop,
88*a27d9013SAlfredo Cardigliano 	.tx_queue_setup         = ionic_dev_tx_queue_setup,
89*a27d9013SAlfredo Cardigliano 	.tx_queue_release       = ionic_dev_tx_queue_release,
90*a27d9013SAlfredo Cardigliano 	.tx_queue_start	        = ionic_dev_tx_queue_start,
91*a27d9013SAlfredo Cardigliano 	.tx_queue_stop          = ionic_dev_tx_queue_stop,
92*a27d9013SAlfredo Cardigliano 	.vlan_offload_set       = ionic_vlan_offload_set,
93669c8de6SAlfredo Cardigliano };
94669c8de6SAlfredo Cardigliano 
95598f6726SAlfredo Cardigliano /*
96598f6726SAlfredo Cardigliano  * Set device link up, enable tx.
97598f6726SAlfredo Cardigliano  */
98598f6726SAlfredo Cardigliano static int
99598f6726SAlfredo Cardigliano ionic_dev_set_link_up(struct rte_eth_dev *eth_dev)
100598f6726SAlfredo Cardigliano {
101598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
102598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
103598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
104598f6726SAlfredo Cardigliano 	int err;
105598f6726SAlfredo Cardigliano 
106598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
107598f6726SAlfredo Cardigliano 
108598f6726SAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
109598f6726SAlfredo Cardigliano 
110598f6726SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
111598f6726SAlfredo Cardigliano 	if (err) {
112598f6726SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port UP");
113598f6726SAlfredo Cardigliano 		return err;
114598f6726SAlfredo Cardigliano 	}
115598f6726SAlfredo Cardigliano 
116598f6726SAlfredo Cardigliano 	return 0;
117598f6726SAlfredo Cardigliano }
118598f6726SAlfredo Cardigliano 
119598f6726SAlfredo Cardigliano /*
120598f6726SAlfredo Cardigliano  * Set device link down, disable tx.
121598f6726SAlfredo Cardigliano  */
122598f6726SAlfredo Cardigliano static int
123598f6726SAlfredo Cardigliano ionic_dev_set_link_down(struct rte_eth_dev *eth_dev)
124598f6726SAlfredo Cardigliano {
125598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
126598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
127598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
128598f6726SAlfredo Cardigliano 	int err;
129598f6726SAlfredo Cardigliano 
130598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
131598f6726SAlfredo Cardigliano 
132598f6726SAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_DOWN);
133598f6726SAlfredo Cardigliano 
134598f6726SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
135598f6726SAlfredo Cardigliano 	if (err) {
136598f6726SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port DOWN");
137598f6726SAlfredo Cardigliano 		return err;
138598f6726SAlfredo Cardigliano 	}
139598f6726SAlfredo Cardigliano 
140598f6726SAlfredo Cardigliano 	return 0;
141598f6726SAlfredo Cardigliano }
142598f6726SAlfredo Cardigliano 
143598f6726SAlfredo Cardigliano static int
144598f6726SAlfredo Cardigliano ionic_dev_link_update(struct rte_eth_dev *eth_dev,
145598f6726SAlfredo Cardigliano 		int wait_to_complete __rte_unused)
146598f6726SAlfredo Cardigliano {
147598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
148598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
149598f6726SAlfredo Cardigliano 	struct rte_eth_link link;
150598f6726SAlfredo Cardigliano 
151598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
152598f6726SAlfredo Cardigliano 
153598f6726SAlfredo Cardigliano 	/* Initialize */
154598f6726SAlfredo Cardigliano 	memset(&link, 0, sizeof(link));
155598f6726SAlfredo Cardigliano 	link.link_autoneg = ETH_LINK_AUTONEG;
156598f6726SAlfredo Cardigliano 
157598f6726SAlfredo Cardigliano 	if (!adapter->link_up) {
158598f6726SAlfredo Cardigliano 		/* Interface is down */
159598f6726SAlfredo Cardigliano 		link.link_status = ETH_LINK_DOWN;
160598f6726SAlfredo Cardigliano 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
161598f6726SAlfredo Cardigliano 		link.link_speed = ETH_SPEED_NUM_NONE;
162598f6726SAlfredo Cardigliano 	} else {
163598f6726SAlfredo Cardigliano 		/* Interface is up */
164598f6726SAlfredo Cardigliano 		link.link_status = ETH_LINK_UP;
165598f6726SAlfredo Cardigliano 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
166598f6726SAlfredo Cardigliano 		switch (adapter->link_speed) {
167598f6726SAlfredo Cardigliano 		case  10000:
168598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_10G;
169598f6726SAlfredo Cardigliano 			break;
170598f6726SAlfredo Cardigliano 		case  25000:
171598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_25G;
172598f6726SAlfredo Cardigliano 			break;
173598f6726SAlfredo Cardigliano 		case  40000:
174598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_40G;
175598f6726SAlfredo Cardigliano 			break;
176598f6726SAlfredo Cardigliano 		case  50000:
177598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_50G;
178598f6726SAlfredo Cardigliano 			break;
179598f6726SAlfredo Cardigliano 		case 100000:
180598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_100G;
181598f6726SAlfredo Cardigliano 			break;
182598f6726SAlfredo Cardigliano 		default:
183598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_NONE;
184598f6726SAlfredo Cardigliano 			break;
185598f6726SAlfredo Cardigliano 		}
186598f6726SAlfredo Cardigliano 	}
187598f6726SAlfredo Cardigliano 
188598f6726SAlfredo Cardigliano 	return rte_eth_linkstatus_set(eth_dev, &link);
189598f6726SAlfredo Cardigliano }
190598f6726SAlfredo Cardigliano 
19127b942c8SAlfredo Cardigliano /**
19227b942c8SAlfredo Cardigliano  * Interrupt handler triggered by NIC for handling
19327b942c8SAlfredo Cardigliano  * specific interrupt.
19427b942c8SAlfredo Cardigliano  *
19527b942c8SAlfredo Cardigliano  * @param param
19627b942c8SAlfredo Cardigliano  *  The address of parameter registered before.
19727b942c8SAlfredo Cardigliano  *
19827b942c8SAlfredo Cardigliano  * @return
19927b942c8SAlfredo Cardigliano  *  void
20027b942c8SAlfredo Cardigliano  */
20127b942c8SAlfredo Cardigliano static void
20227b942c8SAlfredo Cardigliano ionic_dev_interrupt_handler(void *param)
20327b942c8SAlfredo Cardigliano {
20427b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = (struct ionic_adapter *)param;
20527b942c8SAlfredo Cardigliano 	uint32_t i;
20627b942c8SAlfredo Cardigliano 
20727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "->");
20827b942c8SAlfredo Cardigliano 
20927b942c8SAlfredo Cardigliano 	for (i = 0; i < adapter->nlifs; i++) {
21027b942c8SAlfredo Cardigliano 		if (adapter->lifs[i])
21127b942c8SAlfredo Cardigliano 			ionic_notifyq_handler(adapter->lifs[i], -1);
21227b942c8SAlfredo Cardigliano 	}
21327b942c8SAlfredo Cardigliano }
21427b942c8SAlfredo Cardigliano 
215669c8de6SAlfredo Cardigliano static int
216598f6726SAlfredo Cardigliano ionic_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
217598f6726SAlfredo Cardigliano {
218598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
219598f6726SAlfredo Cardigliano 	uint32_t max_frame_size;
220598f6726SAlfredo Cardigliano 	int err;
221598f6726SAlfredo Cardigliano 
222598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
223598f6726SAlfredo Cardigliano 
224598f6726SAlfredo Cardigliano 	/*
225598f6726SAlfredo Cardigliano 	 * Note: mtu check against IONIC_MIN_MTU, IONIC_MAX_MTU
226598f6726SAlfredo Cardigliano 	 * is done by the the API.
227598f6726SAlfredo Cardigliano 	 */
228598f6726SAlfredo Cardigliano 
229598f6726SAlfredo Cardigliano 	/*
230598f6726SAlfredo Cardigliano 	 * Max frame size is MTU + Ethernet header + VLAN + QinQ
231598f6726SAlfredo Cardigliano 	 * (plus ETHER_CRC_LEN if the adapter is able to keep CRC)
232598f6726SAlfredo Cardigliano 	 */
233598f6726SAlfredo Cardigliano 	max_frame_size = mtu + RTE_ETHER_HDR_LEN + 4 + 4;
234598f6726SAlfredo Cardigliano 
235598f6726SAlfredo Cardigliano 	if (eth_dev->data->dev_conf.rxmode.max_rx_pkt_len < max_frame_size)
236598f6726SAlfredo Cardigliano 		return -EINVAL;
237598f6726SAlfredo Cardigliano 
238598f6726SAlfredo Cardigliano 	err = ionic_lif_change_mtu(lif, mtu);
239598f6726SAlfredo Cardigliano 	if (err)
240598f6726SAlfredo Cardigliano 		return err;
241598f6726SAlfredo Cardigliano 
242598f6726SAlfredo Cardigliano 	return 0;
243598f6726SAlfredo Cardigliano }
244598f6726SAlfredo Cardigliano 
245598f6726SAlfredo Cardigliano static int
246598f6726SAlfredo Cardigliano ionic_dev_info_get(struct rte_eth_dev *eth_dev,
247598f6726SAlfredo Cardigliano 		struct rte_eth_dev_info *dev_info)
248598f6726SAlfredo Cardigliano {
249598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
250598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
251598f6726SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
252598f6726SAlfredo Cardigliano 
253598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
254598f6726SAlfredo Cardigliano 
255598f6726SAlfredo Cardigliano 	dev_info->max_rx_queues = (uint16_t)
256598f6726SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
257598f6726SAlfredo Cardigliano 	dev_info->max_tx_queues = (uint16_t)
258598f6726SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
259598f6726SAlfredo Cardigliano 	/* Also add ETHER_CRC_LEN if the adapter is able to keep CRC */
260598f6726SAlfredo Cardigliano 	dev_info->min_rx_bufsize = IONIC_MIN_MTU + RTE_ETHER_HDR_LEN;
261598f6726SAlfredo Cardigliano 	dev_info->max_rx_pktlen = IONIC_MAX_MTU + RTE_ETHER_HDR_LEN;
262598f6726SAlfredo Cardigliano 	dev_info->max_mac_addrs = adapter->max_mac_addrs;
263598f6726SAlfredo Cardigliano 	dev_info->min_mtu = IONIC_MIN_MTU;
264598f6726SAlfredo Cardigliano 	dev_info->max_mtu = IONIC_MAX_MTU;
265598f6726SAlfredo Cardigliano 
266598f6726SAlfredo Cardigliano 	dev_info->speed_capa =
267598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_10G |
268598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_25G |
269598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_40G |
270598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_50G |
271598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_100G;
272598f6726SAlfredo Cardigliano 
273*a27d9013SAlfredo Cardigliano 	/*
274*a27d9013SAlfredo Cardigliano 	 * Per-queue capabilities. Actually most of the offloads are enabled
275*a27d9013SAlfredo Cardigliano 	 * by default on the port and can be used on selected queues (by adding
276*a27d9013SAlfredo Cardigliano 	 * packet flags at runtime when required)
277*a27d9013SAlfredo Cardigliano 	 */
278*a27d9013SAlfredo Cardigliano 
279*a27d9013SAlfredo Cardigliano 	dev_info->rx_queue_offload_capa =
280*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_IPV4_CKSUM |
281*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_UDP_CKSUM |
282*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_TCP_CKSUM |
283*a27d9013SAlfredo Cardigliano 		0;
284*a27d9013SAlfredo Cardigliano 
285*a27d9013SAlfredo Cardigliano 	dev_info->tx_queue_offload_capa =
286*a27d9013SAlfredo Cardigliano 		DEV_TX_OFFLOAD_VLAN_INSERT |
287*a27d9013SAlfredo Cardigliano 		0;
288*a27d9013SAlfredo Cardigliano 
289*a27d9013SAlfredo Cardigliano 	/*
290*a27d9013SAlfredo Cardigliano 	 * Per-port capabilities
291*a27d9013SAlfredo Cardigliano 	 * See ionic_set_features to request and check supported features
292*a27d9013SAlfredo Cardigliano 	 */
293*a27d9013SAlfredo Cardigliano 
294*a27d9013SAlfredo Cardigliano 	dev_info->rx_offload_capa = dev_info->rx_queue_offload_capa |
295*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_JUMBO_FRAME |
296*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_VLAN_FILTER |
297*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_VLAN_STRIP |
298*a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_SCATTER |
299*a27d9013SAlfredo Cardigliano 		0;
300*a27d9013SAlfredo Cardigliano 
301*a27d9013SAlfredo Cardigliano 	dev_info->tx_offload_capa = dev_info->tx_queue_offload_capa |
302*a27d9013SAlfredo Cardigliano 		DEV_TX_OFFLOAD_MULTI_SEGS |
303*a27d9013SAlfredo Cardigliano 		DEV_TX_OFFLOAD_TCP_TSO |
304*a27d9013SAlfredo Cardigliano 		0;
305*a27d9013SAlfredo Cardigliano 
306*a27d9013SAlfredo Cardigliano 	dev_info->rx_desc_lim = rx_desc_lim;
307*a27d9013SAlfredo Cardigliano 	dev_info->tx_desc_lim = tx_desc_lim;
308*a27d9013SAlfredo Cardigliano 
309*a27d9013SAlfredo Cardigliano 	/* Driver-preferred Rx/Tx parameters */
310*a27d9013SAlfredo Cardigliano 	dev_info->default_rxportconf.burst_size = 32;
311*a27d9013SAlfredo Cardigliano 	dev_info->default_txportconf.burst_size = 32;
312*a27d9013SAlfredo Cardigliano 	dev_info->default_rxportconf.nb_queues = 1;
313*a27d9013SAlfredo Cardigliano 	dev_info->default_txportconf.nb_queues = 1;
314*a27d9013SAlfredo Cardigliano 	dev_info->default_rxportconf.ring_size = IONIC_DEF_TXRX_DESC;
315*a27d9013SAlfredo Cardigliano 	dev_info->default_txportconf.ring_size = IONIC_DEF_TXRX_DESC;
316*a27d9013SAlfredo Cardigliano 
317598f6726SAlfredo Cardigliano 	return 0;
318598f6726SAlfredo Cardigliano }
319598f6726SAlfredo Cardigliano 
320598f6726SAlfredo Cardigliano static int
321ec15c66bSAlfredo Cardigliano ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev,
322ec15c66bSAlfredo Cardigliano 		struct rte_eth_fc_conf *fc_conf)
323ec15c66bSAlfredo Cardigliano {
324ec15c66bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
325ec15c66bSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
326ec15c66bSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
327ec15c66bSAlfredo Cardigliano 
328ec15c66bSAlfredo Cardigliano 	if (idev->port_info) {
329ec15c66bSAlfredo Cardigliano 		fc_conf->autoneg = idev->port_info->config.an_enable;
330ec15c66bSAlfredo Cardigliano 
331ec15c66bSAlfredo Cardigliano 		if (idev->port_info->config.pause_type)
332ec15c66bSAlfredo Cardigliano 			fc_conf->mode = RTE_FC_FULL;
333ec15c66bSAlfredo Cardigliano 		else
334ec15c66bSAlfredo Cardigliano 			fc_conf->mode = RTE_FC_NONE;
335ec15c66bSAlfredo Cardigliano 	}
336ec15c66bSAlfredo Cardigliano 
337ec15c66bSAlfredo Cardigliano 	return 0;
338ec15c66bSAlfredo Cardigliano }
339ec15c66bSAlfredo Cardigliano 
340ec15c66bSAlfredo Cardigliano static int
341ec15c66bSAlfredo Cardigliano ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev,
342ec15c66bSAlfredo Cardigliano 		struct rte_eth_fc_conf *fc_conf)
343ec15c66bSAlfredo Cardigliano {
344ec15c66bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
345ec15c66bSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
346ec15c66bSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
347ec15c66bSAlfredo Cardigliano 	uint8_t pause_type = IONIC_PORT_PAUSE_TYPE_NONE;
348ec15c66bSAlfredo Cardigliano 	uint8_t an_enable;
349ec15c66bSAlfredo Cardigliano 
350ec15c66bSAlfredo Cardigliano 	switch (fc_conf->mode) {
351ec15c66bSAlfredo Cardigliano 	case RTE_FC_NONE:
352ec15c66bSAlfredo Cardigliano 		pause_type = IONIC_PORT_PAUSE_TYPE_NONE;
353ec15c66bSAlfredo Cardigliano 		break;
354ec15c66bSAlfredo Cardigliano 	case RTE_FC_FULL:
355ec15c66bSAlfredo Cardigliano 		pause_type = IONIC_PORT_PAUSE_TYPE_LINK;
356ec15c66bSAlfredo Cardigliano 		break;
357ec15c66bSAlfredo Cardigliano 	case RTE_FC_RX_PAUSE:
358ec15c66bSAlfredo Cardigliano 	case RTE_FC_TX_PAUSE:
359ec15c66bSAlfredo Cardigliano 		return -ENOTSUP;
360ec15c66bSAlfredo Cardigliano 	}
361ec15c66bSAlfredo Cardigliano 
362ec15c66bSAlfredo Cardigliano 	an_enable = fc_conf->autoneg;
363ec15c66bSAlfredo Cardigliano 
364ec15c66bSAlfredo Cardigliano 	ionic_dev_cmd_port_pause(idev, pause_type);
365ec15c66bSAlfredo Cardigliano 	ionic_dev_cmd_port_autoneg(idev, an_enable);
366ec15c66bSAlfredo Cardigliano 
367ec15c66bSAlfredo Cardigliano 	return 0;
368ec15c66bSAlfredo Cardigliano }
369ec15c66bSAlfredo Cardigliano 
370ec15c66bSAlfredo Cardigliano static int
371*a27d9013SAlfredo Cardigliano ionic_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
372*a27d9013SAlfredo Cardigliano {
373*a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
374*a27d9013SAlfredo Cardigliano 	struct rte_eth_rxmode *rxmode;
375*a27d9013SAlfredo Cardigliano 	rxmode = &eth_dev->data->dev_conf.rxmode;
376*a27d9013SAlfredo Cardigliano 	int i;
377*a27d9013SAlfredo Cardigliano 
378*a27d9013SAlfredo Cardigliano 	if (mask & ETH_VLAN_STRIP_MASK) {
379*a27d9013SAlfredo Cardigliano 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) {
380*a27d9013SAlfredo Cardigliano 			for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
381*a27d9013SAlfredo Cardigliano 				struct ionic_qcq *rxq =
382*a27d9013SAlfredo Cardigliano 					eth_dev->data->rx_queues[i];
383*a27d9013SAlfredo Cardigliano 				rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
384*a27d9013SAlfredo Cardigliano 			}
385*a27d9013SAlfredo Cardigliano 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
386*a27d9013SAlfredo Cardigliano 		} else {
387*a27d9013SAlfredo Cardigliano 			for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
388*a27d9013SAlfredo Cardigliano 				struct ionic_qcq *rxq =
389*a27d9013SAlfredo Cardigliano 					eth_dev->data->rx_queues[i];
390*a27d9013SAlfredo Cardigliano 				rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
391*a27d9013SAlfredo Cardigliano 			}
392*a27d9013SAlfredo Cardigliano 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
393*a27d9013SAlfredo Cardigliano 		}
394*a27d9013SAlfredo Cardigliano 	}
395*a27d9013SAlfredo Cardigliano 
396*a27d9013SAlfredo Cardigliano 	if (mask & ETH_VLAN_FILTER_MASK) {
397*a27d9013SAlfredo Cardigliano 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
398*a27d9013SAlfredo Cardigliano 			lif->features |= IONIC_ETH_HW_VLAN_RX_FILTER;
399*a27d9013SAlfredo Cardigliano 		else
400*a27d9013SAlfredo Cardigliano 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_FILTER;
401*a27d9013SAlfredo Cardigliano 	}
402*a27d9013SAlfredo Cardigliano 
403*a27d9013SAlfredo Cardigliano 	ionic_lif_set_features(lif);
404*a27d9013SAlfredo Cardigliano 
405*a27d9013SAlfredo Cardigliano 	return 0;
406*a27d9013SAlfredo Cardigliano }
407*a27d9013SAlfredo Cardigliano 
408*a27d9013SAlfredo Cardigliano static int
409598f6726SAlfredo Cardigliano ionic_dev_configure(struct rte_eth_dev *eth_dev)
410598f6726SAlfredo Cardigliano {
411598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
412598f6726SAlfredo Cardigliano 	int err;
413598f6726SAlfredo Cardigliano 
414598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
415598f6726SAlfredo Cardigliano 
416598f6726SAlfredo Cardigliano 	err = ionic_lif_configure(lif);
417598f6726SAlfredo Cardigliano 	if (err) {
418598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot configure LIF: %d", err);
419598f6726SAlfredo Cardigliano 		return err;
420598f6726SAlfredo Cardigliano 	}
421598f6726SAlfredo Cardigliano 
422598f6726SAlfredo Cardigliano 	return 0;
423598f6726SAlfredo Cardigliano }
424598f6726SAlfredo Cardigliano 
425598f6726SAlfredo Cardigliano static inline uint32_t
426598f6726SAlfredo Cardigliano ionic_parse_link_speeds(uint16_t link_speeds)
427598f6726SAlfredo Cardigliano {
428598f6726SAlfredo Cardigliano 	if (link_speeds & ETH_LINK_SPEED_100G)
429598f6726SAlfredo Cardigliano 		return 100000;
430598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_50G)
431598f6726SAlfredo Cardigliano 		return 50000;
432598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_40G)
433598f6726SAlfredo Cardigliano 		return 40000;
434598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_25G)
435598f6726SAlfredo Cardigliano 		return 25000;
436598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_10G)
437598f6726SAlfredo Cardigliano 		return 10000;
438598f6726SAlfredo Cardigliano 	else
439598f6726SAlfredo Cardigliano 		return 0;
440598f6726SAlfredo Cardigliano }
441598f6726SAlfredo Cardigliano 
442598f6726SAlfredo Cardigliano /*
443598f6726SAlfredo Cardigliano  * Configure device link speed and setup link.
444598f6726SAlfredo Cardigliano  * It returns 0 on success.
445598f6726SAlfredo Cardigliano  */
446598f6726SAlfredo Cardigliano static int
447598f6726SAlfredo Cardigliano ionic_dev_start(struct rte_eth_dev *eth_dev)
448598f6726SAlfredo Cardigliano {
449598f6726SAlfredo Cardigliano 	struct rte_eth_conf *dev_conf = &eth_dev->data->dev_conf;
450598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
451598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
452598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
453598f6726SAlfredo Cardigliano 	uint32_t allowed_speeds;
454598f6726SAlfredo Cardigliano 	int err;
455598f6726SAlfredo Cardigliano 
456598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
457598f6726SAlfredo Cardigliano 
458598f6726SAlfredo Cardigliano 	allowed_speeds =
459598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_FIXED |
460598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_10G |
461598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_25G |
462598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_40G |
463598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_50G |
464598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_100G;
465598f6726SAlfredo Cardigliano 
466598f6726SAlfredo Cardigliano 	if (dev_conf->link_speeds & ~allowed_speeds) {
467598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Invalid link setting");
468598f6726SAlfredo Cardigliano 		return -EINVAL;
469598f6726SAlfredo Cardigliano 	}
470598f6726SAlfredo Cardigliano 
471598f6726SAlfredo Cardigliano 	err = ionic_lif_start(lif);
472598f6726SAlfredo Cardigliano 	if (err) {
473598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot start LIF: %d", err);
474598f6726SAlfredo Cardigliano 		return err;
475598f6726SAlfredo Cardigliano 	}
476598f6726SAlfredo Cardigliano 
477598f6726SAlfredo Cardigliano 	if (eth_dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
478598f6726SAlfredo Cardigliano 		uint32_t speed = ionic_parse_link_speeds(dev_conf->link_speeds);
479598f6726SAlfredo Cardigliano 
480598f6726SAlfredo Cardigliano 		if (speed)
481598f6726SAlfredo Cardigliano 			ionic_dev_cmd_port_speed(idev, speed);
482598f6726SAlfredo Cardigliano 	}
483598f6726SAlfredo Cardigliano 
484598f6726SAlfredo Cardigliano 	ionic_dev_link_update(eth_dev, 0);
485598f6726SAlfredo Cardigliano 
486598f6726SAlfredo Cardigliano 	return 0;
487598f6726SAlfredo Cardigliano }
488598f6726SAlfredo Cardigliano 
489598f6726SAlfredo Cardigliano /*
490598f6726SAlfredo Cardigliano  * Stop device: disable rx and tx functions to allow for reconfiguring.
491598f6726SAlfredo Cardigliano  */
492598f6726SAlfredo Cardigliano static void
493598f6726SAlfredo Cardigliano ionic_dev_stop(struct rte_eth_dev *eth_dev)
494598f6726SAlfredo Cardigliano {
495598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
496598f6726SAlfredo Cardigliano 	int err;
497598f6726SAlfredo Cardigliano 
498598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
499598f6726SAlfredo Cardigliano 
500598f6726SAlfredo Cardigliano 	err = ionic_lif_stop(lif);
501598f6726SAlfredo Cardigliano 	if (err)
502598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
503598f6726SAlfredo Cardigliano }
504598f6726SAlfredo Cardigliano 
505598f6726SAlfredo Cardigliano /*
506598f6726SAlfredo Cardigliano  * Reset and stop device.
507598f6726SAlfredo Cardigliano  */
508598f6726SAlfredo Cardigliano static void
509598f6726SAlfredo Cardigliano ionic_dev_close(struct rte_eth_dev *eth_dev)
510598f6726SAlfredo Cardigliano {
511598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
512598f6726SAlfredo Cardigliano 	int err;
513598f6726SAlfredo Cardigliano 
514598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
515598f6726SAlfredo Cardigliano 
516598f6726SAlfredo Cardigliano 	err = ionic_lif_stop(lif);
517598f6726SAlfredo Cardigliano 	if (err) {
518598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
519598f6726SAlfredo Cardigliano 		return;
520598f6726SAlfredo Cardigliano 	}
521598f6726SAlfredo Cardigliano 
522598f6726SAlfredo Cardigliano 	err = eth_ionic_dev_uninit(eth_dev);
523598f6726SAlfredo Cardigliano 	if (err) {
524598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot destroy LIF: %d", err);
525598f6726SAlfredo Cardigliano 		return;
526598f6726SAlfredo Cardigliano 	}
527598f6726SAlfredo Cardigliano }
528598f6726SAlfredo Cardigliano 
529598f6726SAlfredo Cardigliano static int
530669c8de6SAlfredo Cardigliano eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
531669c8de6SAlfredo Cardigliano {
532669c8de6SAlfredo Cardigliano 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
533669c8de6SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
534669c8de6SAlfredo Cardigliano 	struct ionic_adapter *adapter = (struct ionic_adapter *)init_params;
535669c8de6SAlfredo Cardigliano 	int err;
536669c8de6SAlfredo Cardigliano 
537669c8de6SAlfredo Cardigliano 	IONIC_PRINT_CALL();
538669c8de6SAlfredo Cardigliano 
539669c8de6SAlfredo Cardigliano 	eth_dev->dev_ops = &ionic_eth_dev_ops;
540*a27d9013SAlfredo Cardigliano 	eth_dev->rx_pkt_burst = &ionic_recv_pkts;
541*a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_burst = &ionic_xmit_pkts;
542*a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_prepare = &ionic_prep_pkts;
543669c8de6SAlfredo Cardigliano 
544669c8de6SAlfredo Cardigliano 	/* Multi-process not supported, primary does initialization anyway */
545669c8de6SAlfredo Cardigliano 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
546669c8de6SAlfredo Cardigliano 		return 0;
547669c8de6SAlfredo Cardigliano 
548669c8de6SAlfredo Cardigliano 	rte_eth_copy_pci_info(eth_dev, pci_dev);
549669c8de6SAlfredo Cardigliano 
550669c8de6SAlfredo Cardigliano 	lif->index = adapter->nlifs;
551669c8de6SAlfredo Cardigliano 	lif->eth_dev = eth_dev;
552669c8de6SAlfredo Cardigliano 	lif->adapter = adapter;
553669c8de6SAlfredo Cardigliano 	adapter->lifs[adapter->nlifs] = lif;
554669c8de6SAlfredo Cardigliano 
555598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Up to %u MAC addresses supported",
556598f6726SAlfredo Cardigliano 		adapter->max_mac_addrs);
557598f6726SAlfredo Cardigliano 
558598f6726SAlfredo Cardigliano 	/* Allocate memory for storing MAC addresses */
559598f6726SAlfredo Cardigliano 	eth_dev->data->mac_addrs = rte_zmalloc("ionic",
560598f6726SAlfredo Cardigliano 		RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs, 0);
561598f6726SAlfredo Cardigliano 
562598f6726SAlfredo Cardigliano 	if (eth_dev->data->mac_addrs == NULL) {
563598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to allocate %u bytes needed to "
564598f6726SAlfredo Cardigliano 			"store MAC addresses",
565598f6726SAlfredo Cardigliano 			RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs);
566598f6726SAlfredo Cardigliano 		err = -ENOMEM;
567598f6726SAlfredo Cardigliano 		goto err;
568598f6726SAlfredo Cardigliano 	}
569598f6726SAlfredo Cardigliano 
570669c8de6SAlfredo Cardigliano 	err = ionic_lif_alloc(lif);
571669c8de6SAlfredo Cardigliano 	if (err) {
572669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate LIFs: %d, aborting",
573669c8de6SAlfredo Cardigliano 			err);
574669c8de6SAlfredo Cardigliano 		goto err;
575669c8de6SAlfredo Cardigliano 	}
576669c8de6SAlfredo Cardigliano 
577669c8de6SAlfredo Cardigliano 	err = ionic_lif_init(lif);
578669c8de6SAlfredo Cardigliano 	if (err) {
579669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot init LIFs: %d, aborting", err);
580669c8de6SAlfredo Cardigliano 		goto err_free_lif;
581669c8de6SAlfredo Cardigliano 	}
582669c8de6SAlfredo Cardigliano 
583598f6726SAlfredo Cardigliano 	/* Copy the MAC address */
584598f6726SAlfredo Cardigliano 	rte_ether_addr_copy((struct rte_ether_addr *)lif->mac_addr,
585598f6726SAlfredo Cardigliano 		&eth_dev->data->mac_addrs[0]);
586598f6726SAlfredo Cardigliano 
587669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Port %u initialized", eth_dev->data->port_id);
588669c8de6SAlfredo Cardigliano 
589669c8de6SAlfredo Cardigliano 	return 0;
590669c8de6SAlfredo Cardigliano 
591669c8de6SAlfredo Cardigliano err_free_lif:
592669c8de6SAlfredo Cardigliano 	ionic_lif_free(lif);
593669c8de6SAlfredo Cardigliano err:
594669c8de6SAlfredo Cardigliano 	return err;
595669c8de6SAlfredo Cardigliano }
596669c8de6SAlfredo Cardigliano 
597669c8de6SAlfredo Cardigliano static int
598669c8de6SAlfredo Cardigliano eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev)
599669c8de6SAlfredo Cardigliano {
600669c8de6SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
601669c8de6SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
602669c8de6SAlfredo Cardigliano 
603669c8de6SAlfredo Cardigliano 	IONIC_PRINT_CALL();
604669c8de6SAlfredo Cardigliano 
605669c8de6SAlfredo Cardigliano 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
606669c8de6SAlfredo Cardigliano 		return 0;
607669c8de6SAlfredo Cardigliano 
608669c8de6SAlfredo Cardigliano 	adapter->lifs[lif->index] = NULL;
609669c8de6SAlfredo Cardigliano 
610669c8de6SAlfredo Cardigliano 	ionic_lif_deinit(lif);
611669c8de6SAlfredo Cardigliano 	ionic_lif_free(lif);
612669c8de6SAlfredo Cardigliano 
613669c8de6SAlfredo Cardigliano 	eth_dev->dev_ops = NULL;
614*a27d9013SAlfredo Cardigliano 	eth_dev->rx_pkt_burst = NULL;
615*a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_burst = NULL;
616*a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_prepare = NULL;
617669c8de6SAlfredo Cardigliano 
618669c8de6SAlfredo Cardigliano 	return 0;
619669c8de6SAlfredo Cardigliano }
620669c8de6SAlfredo Cardigliano 
6215ef51809SAlfredo Cardigliano static int
62227b942c8SAlfredo Cardigliano ionic_configure_intr(struct ionic_adapter *adapter)
62327b942c8SAlfredo Cardigliano {
62427b942c8SAlfredo Cardigliano 	struct rte_pci_device *pci_dev = adapter->pci_dev;
62527b942c8SAlfredo Cardigliano 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
62627b942c8SAlfredo Cardigliano 	int err;
62727b942c8SAlfredo Cardigliano 
62827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring %u intrs", adapter->nintrs);
62927b942c8SAlfredo Cardigliano 
63027b942c8SAlfredo Cardigliano 	if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
63127b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Fail to create eventfd");
63227b942c8SAlfredo Cardigliano 		return -1;
63327b942c8SAlfredo Cardigliano 	}
63427b942c8SAlfredo Cardigliano 
63527b942c8SAlfredo Cardigliano 	if (rte_intr_dp_is_en(intr_handle))
63627b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
63727b942c8SAlfredo Cardigliano 			"Packet I/O interrupt on datapath is enabled");
63827b942c8SAlfredo Cardigliano 
63927b942c8SAlfredo Cardigliano 	if (!intr_handle->intr_vec) {
64027b942c8SAlfredo Cardigliano 		intr_handle->intr_vec = rte_zmalloc("intr_vec",
64127b942c8SAlfredo Cardigliano 			adapter->nintrs * sizeof(int), 0);
64227b942c8SAlfredo Cardigliano 
64327b942c8SAlfredo Cardigliano 		if (!intr_handle->intr_vec) {
64427b942c8SAlfredo Cardigliano 			IONIC_PRINT(ERR, "Failed to allocate %u vectors",
64527b942c8SAlfredo Cardigliano 				adapter->nintrs);
64627b942c8SAlfredo Cardigliano 			return -ENOMEM;
64727b942c8SAlfredo Cardigliano 		}
64827b942c8SAlfredo Cardigliano 	}
64927b942c8SAlfredo Cardigliano 
65027b942c8SAlfredo Cardigliano 	err = rte_intr_callback_register(intr_handle,
65127b942c8SAlfredo Cardigliano 		ionic_dev_interrupt_handler,
65227b942c8SAlfredo Cardigliano 		adapter);
65327b942c8SAlfredo Cardigliano 
65427b942c8SAlfredo Cardigliano 	if (err) {
65527b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR,
65627b942c8SAlfredo Cardigliano 			"Failure registering interrupts handler (%d)",
65727b942c8SAlfredo Cardigliano 			err);
65827b942c8SAlfredo Cardigliano 		return err;
65927b942c8SAlfredo Cardigliano 	}
66027b942c8SAlfredo Cardigliano 
66127b942c8SAlfredo Cardigliano 	/* enable intr mapping */
66227b942c8SAlfredo Cardigliano 	err = rte_intr_enable(intr_handle);
66327b942c8SAlfredo Cardigliano 
66427b942c8SAlfredo Cardigliano 	if (err) {
66527b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
66627b942c8SAlfredo Cardigliano 		return err;
66727b942c8SAlfredo Cardigliano 	}
66827b942c8SAlfredo Cardigliano 
66927b942c8SAlfredo Cardigliano 	return 0;
67027b942c8SAlfredo Cardigliano }
67127b942c8SAlfredo Cardigliano 
67227b942c8SAlfredo Cardigliano static void
67327b942c8SAlfredo Cardigliano ionic_unconfigure_intr(struct ionic_adapter *adapter)
67427b942c8SAlfredo Cardigliano {
67527b942c8SAlfredo Cardigliano 	struct rte_pci_device *pci_dev = adapter->pci_dev;
67627b942c8SAlfredo Cardigliano 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
67727b942c8SAlfredo Cardigliano 
67827b942c8SAlfredo Cardigliano 	rte_intr_disable(intr_handle);
67927b942c8SAlfredo Cardigliano 
68027b942c8SAlfredo Cardigliano 	rte_intr_callback_unregister(intr_handle,
68127b942c8SAlfredo Cardigliano 		ionic_dev_interrupt_handler,
68227b942c8SAlfredo Cardigliano 		adapter);
68327b942c8SAlfredo Cardigliano }
68427b942c8SAlfredo Cardigliano 
68527b942c8SAlfredo Cardigliano static int
6865ef51809SAlfredo Cardigliano eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
6875ef51809SAlfredo Cardigliano 		struct rte_pci_device *pci_dev)
6885ef51809SAlfredo Cardigliano {
689669c8de6SAlfredo Cardigliano 	char name[RTE_ETH_NAME_MAX_LEN];
6905ef51809SAlfredo Cardigliano 	struct rte_mem_resource *resource;
6915ef51809SAlfredo Cardigliano 	struct ionic_adapter *adapter;
6925ef51809SAlfredo Cardigliano 	struct ionic_hw *hw;
6935ef51809SAlfredo Cardigliano 	unsigned long i;
6945ef51809SAlfredo Cardigliano 	int err;
6955ef51809SAlfredo Cardigliano 
6965ef51809SAlfredo Cardigliano 	/* Check structs (trigger error at compilation time) */
6975ef51809SAlfredo Cardigliano 	ionic_struct_size_checks();
6985ef51809SAlfredo Cardigliano 
6995ef51809SAlfredo Cardigliano 	/* Multi-process not supported */
7005ef51809SAlfredo Cardigliano 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
7015ef51809SAlfredo Cardigliano 		err = -EPERM;
7025ef51809SAlfredo Cardigliano 		goto err;
7035ef51809SAlfredo Cardigliano 	}
7045ef51809SAlfredo Cardigliano 
7055ef51809SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Initializing device %s",
7065ef51809SAlfredo Cardigliano 		pci_dev->device.name);
7075ef51809SAlfredo Cardigliano 
7085ef51809SAlfredo Cardigliano 	adapter = rte_zmalloc("ionic", sizeof(*adapter), 0);
7095ef51809SAlfredo Cardigliano 	if (!adapter) {
7105ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "OOM");
7115ef51809SAlfredo Cardigliano 		err = -ENOMEM;
7125ef51809SAlfredo Cardigliano 		goto err;
7135ef51809SAlfredo Cardigliano 	}
7145ef51809SAlfredo Cardigliano 
7155ef51809SAlfredo Cardigliano 	adapter->pci_dev = pci_dev;
7165ef51809SAlfredo Cardigliano 	hw = &adapter->hw;
7175ef51809SAlfredo Cardigliano 
7185ef51809SAlfredo Cardigliano 	hw->device_id = pci_dev->id.device_id;
7195ef51809SAlfredo Cardigliano 	hw->vendor_id = pci_dev->id.vendor_id;
7205ef51809SAlfredo Cardigliano 
7215ef51809SAlfredo Cardigliano 	err = ionic_init_mac(hw);
7225ef51809SAlfredo Cardigliano 	if (err != 0) {
7235ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Mac init failed: %d", err);
7245ef51809SAlfredo Cardigliano 		err = -EIO;
7255ef51809SAlfredo Cardigliano 		goto err_free_adapter;
7265ef51809SAlfredo Cardigliano 	}
7275ef51809SAlfredo Cardigliano 
7285ef51809SAlfredo Cardigliano 	adapter->is_mgmt_nic = (pci_dev->id.device_id == IONIC_DEV_ID_ETH_MGMT);
7295ef51809SAlfredo Cardigliano 
7305ef51809SAlfredo Cardigliano 	adapter->num_bars = 0;
7315ef51809SAlfredo Cardigliano 	for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
7325ef51809SAlfredo Cardigliano 		resource = &pci_dev->mem_resource[i];
7335ef51809SAlfredo Cardigliano 		if (resource->phys_addr == 0 || resource->len == 0)
7345ef51809SAlfredo Cardigliano 			continue;
7355ef51809SAlfredo Cardigliano 		adapter->bars[adapter->num_bars].vaddr = resource->addr;
7365ef51809SAlfredo Cardigliano 		adapter->bars[adapter->num_bars].bus_addr = resource->phys_addr;
7375ef51809SAlfredo Cardigliano 		adapter->bars[adapter->num_bars].len = resource->len;
7385ef51809SAlfredo Cardigliano 		adapter->num_bars++;
7395ef51809SAlfredo Cardigliano 	}
7405ef51809SAlfredo Cardigliano 
7415ef51809SAlfredo Cardigliano 	/* Discover ionic dev resources */
7425ef51809SAlfredo Cardigliano 
7435ef51809SAlfredo Cardigliano 	err = ionic_setup(adapter);
7445ef51809SAlfredo Cardigliano 	if (err) {
7455ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot setup device: %d, aborting", err);
7465ef51809SAlfredo Cardigliano 		goto err_free_adapter;
7475ef51809SAlfredo Cardigliano 	}
7485ef51809SAlfredo Cardigliano 
7495ef51809SAlfredo Cardigliano 	err = ionic_identify(adapter);
7505ef51809SAlfredo Cardigliano 	if (err) {
7515ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot identify device: %d, aborting",
7525ef51809SAlfredo Cardigliano 			err);
7535ef51809SAlfredo Cardigliano 		goto err_free_adapter;
7545ef51809SAlfredo Cardigliano 	}
7555ef51809SAlfredo Cardigliano 
7565ef51809SAlfredo Cardigliano 	err = ionic_init(adapter);
7575ef51809SAlfredo Cardigliano 	if (err) {
7585ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot init device: %d, aborting", err);
7595ef51809SAlfredo Cardigliano 		goto err_free_adapter;
7605ef51809SAlfredo Cardigliano 	}
7615ef51809SAlfredo Cardigliano 
76223bf4ddbSAlfredo Cardigliano 	/* Configure the ports */
76323bf4ddbSAlfredo Cardigliano 	err = ionic_port_identify(adapter);
76423bf4ddbSAlfredo Cardigliano 	if (err) {
76523bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot identify port: %d, aborting",
76623bf4ddbSAlfredo Cardigliano 			err);
76723bf4ddbSAlfredo Cardigliano 		goto err_free_adapter;
76823bf4ddbSAlfredo Cardigliano 	}
76923bf4ddbSAlfredo Cardigliano 
77023bf4ddbSAlfredo Cardigliano 	err = ionic_port_init(adapter);
77123bf4ddbSAlfredo Cardigliano 	if (err) {
77223bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot init port: %d, aborting", err);
77323bf4ddbSAlfredo Cardigliano 		goto err_free_adapter;
77423bf4ddbSAlfredo Cardigliano 	}
77523bf4ddbSAlfredo Cardigliano 
776669c8de6SAlfredo Cardigliano 	/* Configure LIFs */
777669c8de6SAlfredo Cardigliano 	err = ionic_lif_identify(adapter);
778669c8de6SAlfredo Cardigliano 	if (err) {
779669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot identify lif: %d, aborting", err);
780669c8de6SAlfredo Cardigliano 		goto err_free_adapter;
781669c8de6SAlfredo Cardigliano 	}
782669c8de6SAlfredo Cardigliano 
783669c8de6SAlfredo Cardigliano 	/* Allocate and init LIFs */
784669c8de6SAlfredo Cardigliano 	err = ionic_lifs_size(adapter);
785669c8de6SAlfredo Cardigliano 	if (err) {
786669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot size LIFs: %d, aborting", err);
787669c8de6SAlfredo Cardigliano 		goto err_free_adapter;
788669c8de6SAlfredo Cardigliano 	}
789669c8de6SAlfredo Cardigliano 
790598f6726SAlfredo Cardigliano 	adapter->max_mac_addrs = adapter->ident.lif.eth.max_ucast_filters;
791598f6726SAlfredo Cardigliano 
792669c8de6SAlfredo Cardigliano 	adapter->nlifs = 0;
793669c8de6SAlfredo Cardigliano 	for (i = 0; i < adapter->ident.dev.nlifs; i++) {
794669c8de6SAlfredo Cardigliano 		snprintf(name, sizeof(name), "net_%s_lif_%lu",
795669c8de6SAlfredo Cardigliano 			pci_dev->device.name, i);
796669c8de6SAlfredo Cardigliano 
797669c8de6SAlfredo Cardigliano 		err = rte_eth_dev_create(&pci_dev->device, name,
798669c8de6SAlfredo Cardigliano 			sizeof(struct ionic_lif),
799669c8de6SAlfredo Cardigliano 			NULL, NULL,
800669c8de6SAlfredo Cardigliano 			eth_ionic_dev_init, adapter);
801669c8de6SAlfredo Cardigliano 		if (err) {
802669c8de6SAlfredo Cardigliano 			IONIC_PRINT(ERR, "Cannot create eth device for "
803669c8de6SAlfredo Cardigliano 				"ionic lif %s", name);
804669c8de6SAlfredo Cardigliano 			break;
805669c8de6SAlfredo Cardigliano 		}
806669c8de6SAlfredo Cardigliano 
807669c8de6SAlfredo Cardigliano 		adapter->nlifs++;
808669c8de6SAlfredo Cardigliano 	}
809669c8de6SAlfredo Cardigliano 
81027b942c8SAlfredo Cardigliano 	err = ionic_configure_intr(adapter);
81127b942c8SAlfredo Cardigliano 
81227b942c8SAlfredo Cardigliano 	if (err) {
81327b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to configure interrupts");
81427b942c8SAlfredo Cardigliano 		goto err_free_adapter;
81527b942c8SAlfredo Cardigliano 	}
81627b942c8SAlfredo Cardigliano 
8175ef51809SAlfredo Cardigliano 	return 0;
8185ef51809SAlfredo Cardigliano 
8195ef51809SAlfredo Cardigliano err_free_adapter:
8205ef51809SAlfredo Cardigliano 	rte_free(adapter);
8215ef51809SAlfredo Cardigliano err:
8225ef51809SAlfredo Cardigliano 	return err;
8235ef51809SAlfredo Cardigliano }
8245ef51809SAlfredo Cardigliano 
8255ef51809SAlfredo Cardigliano static int
8265ef51809SAlfredo Cardigliano eth_ionic_pci_remove(struct rte_pci_device *pci_dev __rte_unused)
8275ef51809SAlfredo Cardigliano {
828669c8de6SAlfredo Cardigliano 	char name[RTE_ETH_NAME_MAX_LEN];
829669c8de6SAlfredo Cardigliano 	struct ionic_adapter *adapter = NULL;
830669c8de6SAlfredo Cardigliano 	struct rte_eth_dev *eth_dev;
831669c8de6SAlfredo Cardigliano 	struct ionic_lif *lif;
832669c8de6SAlfredo Cardigliano 	uint32_t i;
833669c8de6SAlfredo Cardigliano 
834669c8de6SAlfredo Cardigliano 	/* Adapter lookup is using (the first) eth_dev name */
835669c8de6SAlfredo Cardigliano 	snprintf(name, sizeof(name), "net_%s_lif_0",
836669c8de6SAlfredo Cardigliano 		pci_dev->device.name);
837669c8de6SAlfredo Cardigliano 
838669c8de6SAlfredo Cardigliano 	eth_dev = rte_eth_dev_allocated(name);
839669c8de6SAlfredo Cardigliano 	if (eth_dev) {
840669c8de6SAlfredo Cardigliano 		lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
841669c8de6SAlfredo Cardigliano 		adapter = lif->adapter;
842669c8de6SAlfredo Cardigliano 	}
843669c8de6SAlfredo Cardigliano 
844669c8de6SAlfredo Cardigliano 	if (adapter) {
84527b942c8SAlfredo Cardigliano 		ionic_unconfigure_intr(adapter);
84627b942c8SAlfredo Cardigliano 
847669c8de6SAlfredo Cardigliano 		for (i = 0; i < adapter->nlifs; i++) {
848669c8de6SAlfredo Cardigliano 			lif = adapter->lifs[i];
849669c8de6SAlfredo Cardigliano 			rte_eth_dev_destroy(lif->eth_dev, eth_ionic_dev_uninit);
850669c8de6SAlfredo Cardigliano 		}
851669c8de6SAlfredo Cardigliano 
852669c8de6SAlfredo Cardigliano 		rte_free(adapter);
853669c8de6SAlfredo Cardigliano 	}
854669c8de6SAlfredo Cardigliano 
8555ef51809SAlfredo Cardigliano 	return 0;
8565ef51809SAlfredo Cardigliano }
8575ef51809SAlfredo Cardigliano 
8585ef51809SAlfredo Cardigliano static struct rte_pci_driver rte_ionic_pmd = {
8595ef51809SAlfredo Cardigliano 	.id_table = pci_id_ionic_map,
8605ef51809SAlfredo Cardigliano 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
8615ef51809SAlfredo Cardigliano 	.probe = eth_ionic_pci_probe,
8625ef51809SAlfredo Cardigliano 	.remove = eth_ionic_pci_remove,
8635ef51809SAlfredo Cardigliano };
8645ef51809SAlfredo Cardigliano 
8655ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI(net_ionic, rte_ionic_pmd);
8665ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI_TABLE(net_ionic, pci_id_ionic_map);
8675ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_KMOD_DEP(net_ionic, "* igb_uio | uio_pci_generic | vfio-pci");
8685ef51809SAlfredo Cardigliano 
8697c125393SAlfredo Cardigliano RTE_INIT(ionic_init_log)
8707c125393SAlfredo Cardigliano {
8717c125393SAlfredo Cardigliano 	ionic_logtype = rte_log_register("pmd.net.ionic");
8727c125393SAlfredo Cardigliano 	if (ionic_logtype >= 0)
8737c125393SAlfredo Cardigliano 		rte_log_set_level(ionic_logtype, RTE_LOG_NOTICE);
8747c125393SAlfredo Cardigliano }
875