xref: /dpdk/drivers/net/ionic/ionic_ethdev.c (revision 22e7171bc63b51f22254b1178cf6c4c290da3bcf)
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"
18a27d9013SAlfredo 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);
37a27d9013SAlfredo Cardigliano static int  ionic_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask);
38*22e7171bSAlfredo Cardigliano static int  ionic_dev_rss_reta_update(struct rte_eth_dev *eth_dev,
39*22e7171bSAlfredo Cardigliano 	struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size);
40*22e7171bSAlfredo Cardigliano static int  ionic_dev_rss_reta_query(struct rte_eth_dev *eth_dev,
41*22e7171bSAlfredo Cardigliano 	struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size);
42*22e7171bSAlfredo Cardigliano static int  ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
43*22e7171bSAlfredo Cardigliano 	struct rte_eth_rss_conf *rss_conf);
44*22e7171bSAlfredo Cardigliano static int  ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev,
45*22e7171bSAlfredo Cardigliano 	struct rte_eth_rss_conf *rss_conf);
467c125393SAlfredo Cardigliano 
477c125393SAlfredo Cardigliano int ionic_logtype;
487c125393SAlfredo Cardigliano 
495ef51809SAlfredo Cardigliano static const struct rte_pci_id pci_id_ionic_map[] = {
505ef51809SAlfredo Cardigliano 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) },
515ef51809SAlfredo Cardigliano 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) },
525ef51809SAlfredo Cardigliano 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) },
535ef51809SAlfredo Cardigliano 	{ .vendor_id = 0, /* sentinel */ },
545ef51809SAlfredo Cardigliano };
555ef51809SAlfredo Cardigliano 
56a27d9013SAlfredo Cardigliano static const struct rte_eth_desc_lim rx_desc_lim = {
57a27d9013SAlfredo Cardigliano 	.nb_max = IONIC_MAX_RING_DESC,
58a27d9013SAlfredo Cardigliano 	.nb_min = IONIC_MIN_RING_DESC,
59a27d9013SAlfredo Cardigliano 	.nb_align = 1,
60a27d9013SAlfredo Cardigliano };
61a27d9013SAlfredo Cardigliano 
62a27d9013SAlfredo Cardigliano static const struct rte_eth_desc_lim tx_desc_lim = {
63a27d9013SAlfredo Cardigliano 	.nb_max = IONIC_MAX_RING_DESC,
64a27d9013SAlfredo Cardigliano 	.nb_min = IONIC_MIN_RING_DESC,
65a27d9013SAlfredo Cardigliano 	.nb_align = 1,
66a27d9013SAlfredo Cardigliano 	.nb_seg_max = IONIC_TX_MAX_SG_ELEMS,
67a27d9013SAlfredo Cardigliano 	.nb_mtu_seg_max = IONIC_TX_MAX_SG_ELEMS,
68a27d9013SAlfredo Cardigliano };
69a27d9013SAlfredo Cardigliano 
70669c8de6SAlfredo Cardigliano static const struct eth_dev_ops ionic_eth_dev_ops = {
71598f6726SAlfredo Cardigliano 	.dev_infos_get          = ionic_dev_info_get,
72598f6726SAlfredo Cardigliano 	.dev_configure          = ionic_dev_configure,
73598f6726SAlfredo Cardigliano 	.mtu_set                = ionic_dev_mtu_set,
74598f6726SAlfredo Cardigliano 	.dev_start              = ionic_dev_start,
75598f6726SAlfredo Cardigliano 	.dev_stop               = ionic_dev_stop,
76598f6726SAlfredo Cardigliano 	.dev_close              = ionic_dev_close,
77598f6726SAlfredo Cardigliano 	.link_update            = ionic_dev_link_update,
78598f6726SAlfredo Cardigliano 	.dev_set_link_up        = ionic_dev_set_link_up,
79598f6726SAlfredo Cardigliano 	.dev_set_link_down      = ionic_dev_set_link_down,
8054fe083fSAlfredo Cardigliano 	.mac_addr_add           = ionic_dev_add_mac,
8154fe083fSAlfredo Cardigliano 	.mac_addr_remove        = ionic_dev_remove_mac,
8254fe083fSAlfredo Cardigliano 	.mac_addr_set           = ionic_dev_set_mac,
8354fe083fSAlfredo Cardigliano 	.vlan_filter_set        = ionic_dev_vlan_filter_set,
8454fe083fSAlfredo Cardigliano 	.promiscuous_enable     = ionic_dev_promiscuous_enable,
8554fe083fSAlfredo Cardigliano 	.promiscuous_disable    = ionic_dev_promiscuous_disable,
8654fe083fSAlfredo Cardigliano 	.allmulticast_enable    = ionic_dev_allmulticast_enable,
8754fe083fSAlfredo Cardigliano 	.allmulticast_disable   = ionic_dev_allmulticast_disable,
88ec15c66bSAlfredo Cardigliano 	.flow_ctrl_get          = ionic_flow_ctrl_get,
89ec15c66bSAlfredo Cardigliano 	.flow_ctrl_set          = ionic_flow_ctrl_set,
90a27d9013SAlfredo Cardigliano 	.rxq_info_get           = ionic_rxq_info_get,
91a27d9013SAlfredo Cardigliano 	.txq_info_get           = ionic_txq_info_get,
92a27d9013SAlfredo Cardigliano 	.rx_queue_setup         = ionic_dev_rx_queue_setup,
93a27d9013SAlfredo Cardigliano 	.rx_queue_release       = ionic_dev_rx_queue_release,
94a27d9013SAlfredo Cardigliano 	.rx_queue_start	        = ionic_dev_rx_queue_start,
95a27d9013SAlfredo Cardigliano 	.rx_queue_stop          = ionic_dev_rx_queue_stop,
96a27d9013SAlfredo Cardigliano 	.tx_queue_setup         = ionic_dev_tx_queue_setup,
97a27d9013SAlfredo Cardigliano 	.tx_queue_release       = ionic_dev_tx_queue_release,
98a27d9013SAlfredo Cardigliano 	.tx_queue_start	        = ionic_dev_tx_queue_start,
99a27d9013SAlfredo Cardigliano 	.tx_queue_stop          = ionic_dev_tx_queue_stop,
100a27d9013SAlfredo Cardigliano 	.vlan_offload_set       = ionic_vlan_offload_set,
101*22e7171bSAlfredo Cardigliano 	.reta_update            = ionic_dev_rss_reta_update,
102*22e7171bSAlfredo Cardigliano 	.reta_query             = ionic_dev_rss_reta_query,
103*22e7171bSAlfredo Cardigliano 	.rss_hash_conf_get      = ionic_dev_rss_hash_conf_get,
104*22e7171bSAlfredo Cardigliano 	.rss_hash_update        = ionic_dev_rss_hash_update,
105669c8de6SAlfredo Cardigliano };
106669c8de6SAlfredo Cardigliano 
107598f6726SAlfredo Cardigliano /*
108598f6726SAlfredo Cardigliano  * Set device link up, enable tx.
109598f6726SAlfredo Cardigliano  */
110598f6726SAlfredo Cardigliano static int
111598f6726SAlfredo Cardigliano ionic_dev_set_link_up(struct rte_eth_dev *eth_dev)
112598f6726SAlfredo Cardigliano {
113598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
114598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
115598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
116598f6726SAlfredo Cardigliano 	int err;
117598f6726SAlfredo Cardigliano 
118598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
119598f6726SAlfredo Cardigliano 
120598f6726SAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
121598f6726SAlfredo Cardigliano 
122598f6726SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
123598f6726SAlfredo Cardigliano 	if (err) {
124598f6726SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port UP");
125598f6726SAlfredo Cardigliano 		return err;
126598f6726SAlfredo Cardigliano 	}
127598f6726SAlfredo Cardigliano 
128598f6726SAlfredo Cardigliano 	return 0;
129598f6726SAlfredo Cardigliano }
130598f6726SAlfredo Cardigliano 
131598f6726SAlfredo Cardigliano /*
132598f6726SAlfredo Cardigliano  * Set device link down, disable tx.
133598f6726SAlfredo Cardigliano  */
134598f6726SAlfredo Cardigliano static int
135598f6726SAlfredo Cardigliano ionic_dev_set_link_down(struct rte_eth_dev *eth_dev)
136598f6726SAlfredo Cardigliano {
137598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
138598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
139598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
140598f6726SAlfredo Cardigliano 	int err;
141598f6726SAlfredo Cardigliano 
142598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
143598f6726SAlfredo Cardigliano 
144598f6726SAlfredo Cardigliano 	ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_DOWN);
145598f6726SAlfredo Cardigliano 
146598f6726SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
147598f6726SAlfredo Cardigliano 	if (err) {
148598f6726SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Failed to bring port DOWN");
149598f6726SAlfredo Cardigliano 		return err;
150598f6726SAlfredo Cardigliano 	}
151598f6726SAlfredo Cardigliano 
152598f6726SAlfredo Cardigliano 	return 0;
153598f6726SAlfredo Cardigliano }
154598f6726SAlfredo Cardigliano 
155598f6726SAlfredo Cardigliano static int
156598f6726SAlfredo Cardigliano ionic_dev_link_update(struct rte_eth_dev *eth_dev,
157598f6726SAlfredo Cardigliano 		int wait_to_complete __rte_unused)
158598f6726SAlfredo Cardigliano {
159598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
160598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
161598f6726SAlfredo Cardigliano 	struct rte_eth_link link;
162598f6726SAlfredo Cardigliano 
163598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
164598f6726SAlfredo Cardigliano 
165598f6726SAlfredo Cardigliano 	/* Initialize */
166598f6726SAlfredo Cardigliano 	memset(&link, 0, sizeof(link));
167598f6726SAlfredo Cardigliano 	link.link_autoneg = ETH_LINK_AUTONEG;
168598f6726SAlfredo Cardigliano 
169598f6726SAlfredo Cardigliano 	if (!adapter->link_up) {
170598f6726SAlfredo Cardigliano 		/* Interface is down */
171598f6726SAlfredo Cardigliano 		link.link_status = ETH_LINK_DOWN;
172598f6726SAlfredo Cardigliano 		link.link_duplex = ETH_LINK_HALF_DUPLEX;
173598f6726SAlfredo Cardigliano 		link.link_speed = ETH_SPEED_NUM_NONE;
174598f6726SAlfredo Cardigliano 	} else {
175598f6726SAlfredo Cardigliano 		/* Interface is up */
176598f6726SAlfredo Cardigliano 		link.link_status = ETH_LINK_UP;
177598f6726SAlfredo Cardigliano 		link.link_duplex = ETH_LINK_FULL_DUPLEX;
178598f6726SAlfredo Cardigliano 		switch (adapter->link_speed) {
179598f6726SAlfredo Cardigliano 		case  10000:
180598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_10G;
181598f6726SAlfredo Cardigliano 			break;
182598f6726SAlfredo Cardigliano 		case  25000:
183598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_25G;
184598f6726SAlfredo Cardigliano 			break;
185598f6726SAlfredo Cardigliano 		case  40000:
186598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_40G;
187598f6726SAlfredo Cardigliano 			break;
188598f6726SAlfredo Cardigliano 		case  50000:
189598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_50G;
190598f6726SAlfredo Cardigliano 			break;
191598f6726SAlfredo Cardigliano 		case 100000:
192598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_100G;
193598f6726SAlfredo Cardigliano 			break;
194598f6726SAlfredo Cardigliano 		default:
195598f6726SAlfredo Cardigliano 			link.link_speed = ETH_SPEED_NUM_NONE;
196598f6726SAlfredo Cardigliano 			break;
197598f6726SAlfredo Cardigliano 		}
198598f6726SAlfredo Cardigliano 	}
199598f6726SAlfredo Cardigliano 
200598f6726SAlfredo Cardigliano 	return rte_eth_linkstatus_set(eth_dev, &link);
201598f6726SAlfredo Cardigliano }
202598f6726SAlfredo Cardigliano 
20327b942c8SAlfredo Cardigliano /**
20427b942c8SAlfredo Cardigliano  * Interrupt handler triggered by NIC for handling
20527b942c8SAlfredo Cardigliano  * specific interrupt.
20627b942c8SAlfredo Cardigliano  *
20727b942c8SAlfredo Cardigliano  * @param param
20827b942c8SAlfredo Cardigliano  *  The address of parameter registered before.
20927b942c8SAlfredo Cardigliano  *
21027b942c8SAlfredo Cardigliano  * @return
21127b942c8SAlfredo Cardigliano  *  void
21227b942c8SAlfredo Cardigliano  */
21327b942c8SAlfredo Cardigliano static void
21427b942c8SAlfredo Cardigliano ionic_dev_interrupt_handler(void *param)
21527b942c8SAlfredo Cardigliano {
21627b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = (struct ionic_adapter *)param;
21727b942c8SAlfredo Cardigliano 	uint32_t i;
21827b942c8SAlfredo Cardigliano 
21927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "->");
22027b942c8SAlfredo Cardigliano 
22127b942c8SAlfredo Cardigliano 	for (i = 0; i < adapter->nlifs; i++) {
22227b942c8SAlfredo Cardigliano 		if (adapter->lifs[i])
22327b942c8SAlfredo Cardigliano 			ionic_notifyq_handler(adapter->lifs[i], -1);
22427b942c8SAlfredo Cardigliano 	}
22527b942c8SAlfredo Cardigliano }
22627b942c8SAlfredo Cardigliano 
227669c8de6SAlfredo Cardigliano static int
228598f6726SAlfredo Cardigliano ionic_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
229598f6726SAlfredo Cardigliano {
230598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
231598f6726SAlfredo Cardigliano 	uint32_t max_frame_size;
232598f6726SAlfredo Cardigliano 	int err;
233598f6726SAlfredo Cardigliano 
234598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
235598f6726SAlfredo Cardigliano 
236598f6726SAlfredo Cardigliano 	/*
237598f6726SAlfredo Cardigliano 	 * Note: mtu check against IONIC_MIN_MTU, IONIC_MAX_MTU
238598f6726SAlfredo Cardigliano 	 * is done by the the API.
239598f6726SAlfredo Cardigliano 	 */
240598f6726SAlfredo Cardigliano 
241598f6726SAlfredo Cardigliano 	/*
242598f6726SAlfredo Cardigliano 	 * Max frame size is MTU + Ethernet header + VLAN + QinQ
243598f6726SAlfredo Cardigliano 	 * (plus ETHER_CRC_LEN if the adapter is able to keep CRC)
244598f6726SAlfredo Cardigliano 	 */
245598f6726SAlfredo Cardigliano 	max_frame_size = mtu + RTE_ETHER_HDR_LEN + 4 + 4;
246598f6726SAlfredo Cardigliano 
247598f6726SAlfredo Cardigliano 	if (eth_dev->data->dev_conf.rxmode.max_rx_pkt_len < max_frame_size)
248598f6726SAlfredo Cardigliano 		return -EINVAL;
249598f6726SAlfredo Cardigliano 
250598f6726SAlfredo Cardigliano 	err = ionic_lif_change_mtu(lif, mtu);
251598f6726SAlfredo Cardigliano 	if (err)
252598f6726SAlfredo Cardigliano 		return err;
253598f6726SAlfredo Cardigliano 
254598f6726SAlfredo Cardigliano 	return 0;
255598f6726SAlfredo Cardigliano }
256598f6726SAlfredo Cardigliano 
257598f6726SAlfredo Cardigliano static int
258598f6726SAlfredo Cardigliano ionic_dev_info_get(struct rte_eth_dev *eth_dev,
259598f6726SAlfredo Cardigliano 		struct rte_eth_dev_info *dev_info)
260598f6726SAlfredo Cardigliano {
261598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
262598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
263598f6726SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
264598f6726SAlfredo Cardigliano 
265598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
266598f6726SAlfredo Cardigliano 
267598f6726SAlfredo Cardigliano 	dev_info->max_rx_queues = (uint16_t)
268598f6726SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
269598f6726SAlfredo Cardigliano 	dev_info->max_tx_queues = (uint16_t)
270598f6726SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
271598f6726SAlfredo Cardigliano 	/* Also add ETHER_CRC_LEN if the adapter is able to keep CRC */
272598f6726SAlfredo Cardigliano 	dev_info->min_rx_bufsize = IONIC_MIN_MTU + RTE_ETHER_HDR_LEN;
273598f6726SAlfredo Cardigliano 	dev_info->max_rx_pktlen = IONIC_MAX_MTU + RTE_ETHER_HDR_LEN;
274598f6726SAlfredo Cardigliano 	dev_info->max_mac_addrs = adapter->max_mac_addrs;
275598f6726SAlfredo Cardigliano 	dev_info->min_mtu = IONIC_MIN_MTU;
276598f6726SAlfredo Cardigliano 	dev_info->max_mtu = IONIC_MAX_MTU;
277598f6726SAlfredo Cardigliano 
278*22e7171bSAlfredo Cardigliano 	dev_info->hash_key_size = IONIC_RSS_HASH_KEY_SIZE;
279*22e7171bSAlfredo Cardigliano 	dev_info->reta_size = ident->lif.eth.rss_ind_tbl_sz;
280*22e7171bSAlfredo Cardigliano 	dev_info->flow_type_rss_offloads = IONIC_ETH_RSS_OFFLOAD_ALL;
281*22e7171bSAlfredo Cardigliano 
282598f6726SAlfredo Cardigliano 	dev_info->speed_capa =
283598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_10G |
284598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_25G |
285598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_40G |
286598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_50G |
287598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_100G;
288598f6726SAlfredo Cardigliano 
289a27d9013SAlfredo Cardigliano 	/*
290a27d9013SAlfredo Cardigliano 	 * Per-queue capabilities. Actually most of the offloads are enabled
291a27d9013SAlfredo Cardigliano 	 * by default on the port and can be used on selected queues (by adding
292a27d9013SAlfredo Cardigliano 	 * packet flags at runtime when required)
293a27d9013SAlfredo Cardigliano 	 */
294a27d9013SAlfredo Cardigliano 
295a27d9013SAlfredo Cardigliano 	dev_info->rx_queue_offload_capa =
296a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_IPV4_CKSUM |
297a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_UDP_CKSUM |
298a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_TCP_CKSUM |
299a27d9013SAlfredo Cardigliano 		0;
300a27d9013SAlfredo Cardigliano 
301a27d9013SAlfredo Cardigliano 	dev_info->tx_queue_offload_capa =
302a27d9013SAlfredo Cardigliano 		DEV_TX_OFFLOAD_VLAN_INSERT |
303a27d9013SAlfredo Cardigliano 		0;
304a27d9013SAlfredo Cardigliano 
305a27d9013SAlfredo Cardigliano 	/*
306a27d9013SAlfredo Cardigliano 	 * Per-port capabilities
307a27d9013SAlfredo Cardigliano 	 * See ionic_set_features to request and check supported features
308a27d9013SAlfredo Cardigliano 	 */
309a27d9013SAlfredo Cardigliano 
310a27d9013SAlfredo Cardigliano 	dev_info->rx_offload_capa = dev_info->rx_queue_offload_capa |
311a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_JUMBO_FRAME |
312a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_VLAN_FILTER |
313a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_VLAN_STRIP |
314a27d9013SAlfredo Cardigliano 		DEV_RX_OFFLOAD_SCATTER |
315a27d9013SAlfredo Cardigliano 		0;
316a27d9013SAlfredo Cardigliano 
317a27d9013SAlfredo Cardigliano 	dev_info->tx_offload_capa = dev_info->tx_queue_offload_capa |
318a27d9013SAlfredo Cardigliano 		DEV_TX_OFFLOAD_MULTI_SEGS |
319a27d9013SAlfredo Cardigliano 		DEV_TX_OFFLOAD_TCP_TSO |
320a27d9013SAlfredo Cardigliano 		0;
321a27d9013SAlfredo Cardigliano 
322a27d9013SAlfredo Cardigliano 	dev_info->rx_desc_lim = rx_desc_lim;
323a27d9013SAlfredo Cardigliano 	dev_info->tx_desc_lim = tx_desc_lim;
324a27d9013SAlfredo Cardigliano 
325a27d9013SAlfredo Cardigliano 	/* Driver-preferred Rx/Tx parameters */
326a27d9013SAlfredo Cardigliano 	dev_info->default_rxportconf.burst_size = 32;
327a27d9013SAlfredo Cardigliano 	dev_info->default_txportconf.burst_size = 32;
328a27d9013SAlfredo Cardigliano 	dev_info->default_rxportconf.nb_queues = 1;
329a27d9013SAlfredo Cardigliano 	dev_info->default_txportconf.nb_queues = 1;
330a27d9013SAlfredo Cardigliano 	dev_info->default_rxportconf.ring_size = IONIC_DEF_TXRX_DESC;
331a27d9013SAlfredo Cardigliano 	dev_info->default_txportconf.ring_size = IONIC_DEF_TXRX_DESC;
332a27d9013SAlfredo Cardigliano 
333598f6726SAlfredo Cardigliano 	return 0;
334598f6726SAlfredo Cardigliano }
335598f6726SAlfredo Cardigliano 
336598f6726SAlfredo Cardigliano static int
337ec15c66bSAlfredo Cardigliano ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev,
338ec15c66bSAlfredo Cardigliano 		struct rte_eth_fc_conf *fc_conf)
339ec15c66bSAlfredo Cardigliano {
340ec15c66bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
341ec15c66bSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
342ec15c66bSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
343ec15c66bSAlfredo Cardigliano 
344ec15c66bSAlfredo Cardigliano 	if (idev->port_info) {
345ec15c66bSAlfredo Cardigliano 		fc_conf->autoneg = idev->port_info->config.an_enable;
346ec15c66bSAlfredo Cardigliano 
347ec15c66bSAlfredo Cardigliano 		if (idev->port_info->config.pause_type)
348ec15c66bSAlfredo Cardigliano 			fc_conf->mode = RTE_FC_FULL;
349ec15c66bSAlfredo Cardigliano 		else
350ec15c66bSAlfredo Cardigliano 			fc_conf->mode = RTE_FC_NONE;
351ec15c66bSAlfredo Cardigliano 	}
352ec15c66bSAlfredo Cardigliano 
353ec15c66bSAlfredo Cardigliano 	return 0;
354ec15c66bSAlfredo Cardigliano }
355ec15c66bSAlfredo Cardigliano 
356ec15c66bSAlfredo Cardigliano static int
357ec15c66bSAlfredo Cardigliano ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev,
358ec15c66bSAlfredo Cardigliano 		struct rte_eth_fc_conf *fc_conf)
359ec15c66bSAlfredo Cardigliano {
360ec15c66bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
361ec15c66bSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
362ec15c66bSAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
363ec15c66bSAlfredo Cardigliano 	uint8_t pause_type = IONIC_PORT_PAUSE_TYPE_NONE;
364ec15c66bSAlfredo Cardigliano 	uint8_t an_enable;
365ec15c66bSAlfredo Cardigliano 
366ec15c66bSAlfredo Cardigliano 	switch (fc_conf->mode) {
367ec15c66bSAlfredo Cardigliano 	case RTE_FC_NONE:
368ec15c66bSAlfredo Cardigliano 		pause_type = IONIC_PORT_PAUSE_TYPE_NONE;
369ec15c66bSAlfredo Cardigliano 		break;
370ec15c66bSAlfredo Cardigliano 	case RTE_FC_FULL:
371ec15c66bSAlfredo Cardigliano 		pause_type = IONIC_PORT_PAUSE_TYPE_LINK;
372ec15c66bSAlfredo Cardigliano 		break;
373ec15c66bSAlfredo Cardigliano 	case RTE_FC_RX_PAUSE:
374ec15c66bSAlfredo Cardigliano 	case RTE_FC_TX_PAUSE:
375ec15c66bSAlfredo Cardigliano 		return -ENOTSUP;
376ec15c66bSAlfredo Cardigliano 	}
377ec15c66bSAlfredo Cardigliano 
378ec15c66bSAlfredo Cardigliano 	an_enable = fc_conf->autoneg;
379ec15c66bSAlfredo Cardigliano 
380ec15c66bSAlfredo Cardigliano 	ionic_dev_cmd_port_pause(idev, pause_type);
381ec15c66bSAlfredo Cardigliano 	ionic_dev_cmd_port_autoneg(idev, an_enable);
382ec15c66bSAlfredo Cardigliano 
383ec15c66bSAlfredo Cardigliano 	return 0;
384ec15c66bSAlfredo Cardigliano }
385ec15c66bSAlfredo Cardigliano 
386ec15c66bSAlfredo Cardigliano static int
387a27d9013SAlfredo Cardigliano ionic_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
388a27d9013SAlfredo Cardigliano {
389a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
390a27d9013SAlfredo Cardigliano 	struct rte_eth_rxmode *rxmode;
391a27d9013SAlfredo Cardigliano 	rxmode = &eth_dev->data->dev_conf.rxmode;
392a27d9013SAlfredo Cardigliano 	int i;
393a27d9013SAlfredo Cardigliano 
394a27d9013SAlfredo Cardigliano 	if (mask & ETH_VLAN_STRIP_MASK) {
395a27d9013SAlfredo Cardigliano 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) {
396a27d9013SAlfredo Cardigliano 			for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
397a27d9013SAlfredo Cardigliano 				struct ionic_qcq *rxq =
398a27d9013SAlfredo Cardigliano 					eth_dev->data->rx_queues[i];
399a27d9013SAlfredo Cardigliano 				rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
400a27d9013SAlfredo Cardigliano 			}
401a27d9013SAlfredo Cardigliano 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
402a27d9013SAlfredo Cardigliano 		} else {
403a27d9013SAlfredo Cardigliano 			for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
404a27d9013SAlfredo Cardigliano 				struct ionic_qcq *rxq =
405a27d9013SAlfredo Cardigliano 					eth_dev->data->rx_queues[i];
406a27d9013SAlfredo Cardigliano 				rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
407a27d9013SAlfredo Cardigliano 			}
408a27d9013SAlfredo Cardigliano 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
409a27d9013SAlfredo Cardigliano 		}
410a27d9013SAlfredo Cardigliano 	}
411a27d9013SAlfredo Cardigliano 
412a27d9013SAlfredo Cardigliano 	if (mask & ETH_VLAN_FILTER_MASK) {
413a27d9013SAlfredo Cardigliano 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
414a27d9013SAlfredo Cardigliano 			lif->features |= IONIC_ETH_HW_VLAN_RX_FILTER;
415a27d9013SAlfredo Cardigliano 		else
416a27d9013SAlfredo Cardigliano 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_FILTER;
417a27d9013SAlfredo Cardigliano 	}
418a27d9013SAlfredo Cardigliano 
419a27d9013SAlfredo Cardigliano 	ionic_lif_set_features(lif);
420a27d9013SAlfredo Cardigliano 
421a27d9013SAlfredo Cardigliano 	return 0;
422a27d9013SAlfredo Cardigliano }
423a27d9013SAlfredo Cardigliano 
424a27d9013SAlfredo Cardigliano static int
425*22e7171bSAlfredo Cardigliano ionic_dev_rss_reta_update(struct rte_eth_dev *eth_dev,
426*22e7171bSAlfredo Cardigliano 		struct rte_eth_rss_reta_entry64 *reta_conf,
427*22e7171bSAlfredo Cardigliano 		uint16_t reta_size)
428*22e7171bSAlfredo Cardigliano {
429*22e7171bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
430*22e7171bSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
431*22e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
432*22e7171bSAlfredo Cardigliano 	uint32_t i, j, index, num;
433*22e7171bSAlfredo Cardigliano 
434*22e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
435*22e7171bSAlfredo Cardigliano 
436*22e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl) {
437*22e7171bSAlfredo Cardigliano 		IONIC_PRINT(ERR, "RSS RETA not initialized, "
438*22e7171bSAlfredo Cardigliano 			"can't update the table");
439*22e7171bSAlfredo Cardigliano 		return -EINVAL;
440*22e7171bSAlfredo Cardigliano 	}
441*22e7171bSAlfredo Cardigliano 
442*22e7171bSAlfredo Cardigliano 	if (reta_size != ident->lif.eth.rss_ind_tbl_sz) {
443*22e7171bSAlfredo Cardigliano 		IONIC_PRINT(ERR, "The size of hash lookup table configured "
444*22e7171bSAlfredo Cardigliano 			"(%d) doesn't match the number hardware can supported "
445*22e7171bSAlfredo Cardigliano 			"(%d)",
446*22e7171bSAlfredo Cardigliano 			reta_size, ident->lif.eth.rss_ind_tbl_sz);
447*22e7171bSAlfredo Cardigliano 		return -EINVAL;
448*22e7171bSAlfredo Cardigliano 	}
449*22e7171bSAlfredo Cardigliano 
450*22e7171bSAlfredo Cardigliano 	num = lif->adapter->ident.lif.eth.rss_ind_tbl_sz / RTE_RETA_GROUP_SIZE;
451*22e7171bSAlfredo Cardigliano 
452*22e7171bSAlfredo Cardigliano 	for (i = 0; i < num; i++) {
453*22e7171bSAlfredo Cardigliano 		for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) {
454*22e7171bSAlfredo Cardigliano 			if (reta_conf[i].mask & ((uint64_t)1 << j)) {
455*22e7171bSAlfredo Cardigliano 				index = (i * RTE_RETA_GROUP_SIZE) + j;
456*22e7171bSAlfredo Cardigliano 				lif->rss_ind_tbl[index] = reta_conf[i].reta[j];
457*22e7171bSAlfredo Cardigliano 			}
458*22e7171bSAlfredo Cardigliano 		}
459*22e7171bSAlfredo Cardigliano 	}
460*22e7171bSAlfredo Cardigliano 
461*22e7171bSAlfredo Cardigliano 	return ionic_lif_rss_config(lif, lif->rss_types, NULL, NULL);
462*22e7171bSAlfredo Cardigliano }
463*22e7171bSAlfredo Cardigliano 
464*22e7171bSAlfredo Cardigliano static int
465*22e7171bSAlfredo Cardigliano ionic_dev_rss_reta_query(struct rte_eth_dev *eth_dev,
466*22e7171bSAlfredo Cardigliano 		struct rte_eth_rss_reta_entry64 *reta_conf,
467*22e7171bSAlfredo Cardigliano 		uint16_t reta_size)
468*22e7171bSAlfredo Cardigliano {
469*22e7171bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
470*22e7171bSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
471*22e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
472*22e7171bSAlfredo Cardigliano 	int i, num;
473*22e7171bSAlfredo Cardigliano 
474*22e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
475*22e7171bSAlfredo Cardigliano 
476*22e7171bSAlfredo Cardigliano 	if (reta_size != ident->lif.eth.rss_ind_tbl_sz) {
477*22e7171bSAlfredo Cardigliano 		IONIC_PRINT(ERR, "The size of hash lookup table configured "
478*22e7171bSAlfredo Cardigliano 			"(%d) doesn't match the number hardware can supported "
479*22e7171bSAlfredo Cardigliano 			"(%d)",
480*22e7171bSAlfredo Cardigliano 			reta_size, ident->lif.eth.rss_ind_tbl_sz);
481*22e7171bSAlfredo Cardigliano 		return -EINVAL;
482*22e7171bSAlfredo Cardigliano 	}
483*22e7171bSAlfredo Cardigliano 
484*22e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl) {
485*22e7171bSAlfredo Cardigliano 		IONIC_PRINT(ERR, "RSS RETA has not been built yet");
486*22e7171bSAlfredo Cardigliano 		return -EINVAL;
487*22e7171bSAlfredo Cardigliano 	}
488*22e7171bSAlfredo Cardigliano 
489*22e7171bSAlfredo Cardigliano 	num = reta_size / RTE_RETA_GROUP_SIZE;
490*22e7171bSAlfredo Cardigliano 
491*22e7171bSAlfredo Cardigliano 	for (i = 0; i < num; i++) {
492*22e7171bSAlfredo Cardigliano 		memcpy(reta_conf->reta,
493*22e7171bSAlfredo Cardigliano 			&lif->rss_ind_tbl[i * RTE_RETA_GROUP_SIZE],
494*22e7171bSAlfredo Cardigliano 			RTE_RETA_GROUP_SIZE);
495*22e7171bSAlfredo Cardigliano 		reta_conf++;
496*22e7171bSAlfredo Cardigliano 	}
497*22e7171bSAlfredo Cardigliano 
498*22e7171bSAlfredo Cardigliano 	return 0;
499*22e7171bSAlfredo Cardigliano }
500*22e7171bSAlfredo Cardigliano 
501*22e7171bSAlfredo Cardigliano static int
502*22e7171bSAlfredo Cardigliano ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
503*22e7171bSAlfredo Cardigliano 		struct rte_eth_rss_conf *rss_conf)
504*22e7171bSAlfredo Cardigliano {
505*22e7171bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
506*22e7171bSAlfredo Cardigliano 	uint64_t rss_hf = 0;
507*22e7171bSAlfredo Cardigliano 
508*22e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
509*22e7171bSAlfredo Cardigliano 
510*22e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl) {
511*22e7171bSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "RSS not enabled");
512*22e7171bSAlfredo Cardigliano 		return 0;
513*22e7171bSAlfredo Cardigliano 	}
514*22e7171bSAlfredo Cardigliano 
515*22e7171bSAlfredo Cardigliano 	/* Get key value (if not null, rss_key is 40-byte) */
516*22e7171bSAlfredo Cardigliano 	if (rss_conf->rss_key != NULL &&
517*22e7171bSAlfredo Cardigliano 			rss_conf->rss_key_len >= IONIC_RSS_HASH_KEY_SIZE)
518*22e7171bSAlfredo Cardigliano 		memcpy(rss_conf->rss_key, lif->rss_hash_key,
519*22e7171bSAlfredo Cardigliano 			IONIC_RSS_HASH_KEY_SIZE);
520*22e7171bSAlfredo Cardigliano 
521*22e7171bSAlfredo Cardigliano 	if (lif->rss_types & IONIC_RSS_TYPE_IPV4)
522*22e7171bSAlfredo Cardigliano 		rss_hf |= ETH_RSS_IPV4;
523*22e7171bSAlfredo Cardigliano 	if (lif->rss_types & IONIC_RSS_TYPE_IPV4_TCP)
524*22e7171bSAlfredo Cardigliano 		rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;
525*22e7171bSAlfredo Cardigliano 	if (lif->rss_types & IONIC_RSS_TYPE_IPV4_UDP)
526*22e7171bSAlfredo Cardigliano 		rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
527*22e7171bSAlfredo Cardigliano 	if (lif->rss_types & IONIC_RSS_TYPE_IPV6)
528*22e7171bSAlfredo Cardigliano 		rss_hf |= ETH_RSS_IPV6;
529*22e7171bSAlfredo Cardigliano 	if (lif->rss_types & IONIC_RSS_TYPE_IPV6_TCP)
530*22e7171bSAlfredo Cardigliano 		rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;
531*22e7171bSAlfredo Cardigliano 	if (lif->rss_types & IONIC_RSS_TYPE_IPV6_UDP)
532*22e7171bSAlfredo Cardigliano 		rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
533*22e7171bSAlfredo Cardigliano 
534*22e7171bSAlfredo Cardigliano 	rss_conf->rss_hf = rss_hf;
535*22e7171bSAlfredo Cardigliano 
536*22e7171bSAlfredo Cardigliano 	return 0;
537*22e7171bSAlfredo Cardigliano }
538*22e7171bSAlfredo Cardigliano 
539*22e7171bSAlfredo Cardigliano static int
540*22e7171bSAlfredo Cardigliano ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev,
541*22e7171bSAlfredo Cardigliano 		struct rte_eth_rss_conf *rss_conf)
542*22e7171bSAlfredo Cardigliano {
543*22e7171bSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
544*22e7171bSAlfredo Cardigliano 	uint32_t rss_types = 0;
545*22e7171bSAlfredo Cardigliano 	uint8_t *key = NULL;
546*22e7171bSAlfredo Cardigliano 
547*22e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
548*22e7171bSAlfredo Cardigliano 
549*22e7171bSAlfredo Cardigliano 	if (rss_conf->rss_key)
550*22e7171bSAlfredo Cardigliano 		key = rss_conf->rss_key;
551*22e7171bSAlfredo Cardigliano 
552*22e7171bSAlfredo Cardigliano 	if ((rss_conf->rss_hf & IONIC_ETH_RSS_OFFLOAD_ALL) == 0) {
553*22e7171bSAlfredo Cardigliano 		/*
554*22e7171bSAlfredo Cardigliano 		 * Can't disable rss through hash flags,
555*22e7171bSAlfredo Cardigliano 		 * if it is enabled by default during init
556*22e7171bSAlfredo Cardigliano 		 */
557*22e7171bSAlfredo Cardigliano 		if (lif->rss_ind_tbl)
558*22e7171bSAlfredo Cardigliano 			return -EINVAL;
559*22e7171bSAlfredo Cardigliano 	} else {
560*22e7171bSAlfredo Cardigliano 		/* Can't enable rss if disabled by default during init */
561*22e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl)
562*22e7171bSAlfredo Cardigliano 			return -EINVAL;
563*22e7171bSAlfredo Cardigliano 
564*22e7171bSAlfredo Cardigliano 		if (rss_conf->rss_hf & ETH_RSS_IPV4)
565*22e7171bSAlfredo Cardigliano 			rss_types |= IONIC_RSS_TYPE_IPV4;
566*22e7171bSAlfredo Cardigliano 		if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
567*22e7171bSAlfredo Cardigliano 			rss_types |= IONIC_RSS_TYPE_IPV4_TCP;
568*22e7171bSAlfredo Cardigliano 		if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)
569*22e7171bSAlfredo Cardigliano 			rss_types |= IONIC_RSS_TYPE_IPV4_UDP;
570*22e7171bSAlfredo Cardigliano 		if (rss_conf->rss_hf & ETH_RSS_IPV6)
571*22e7171bSAlfredo Cardigliano 			rss_types |= IONIC_RSS_TYPE_IPV6;
572*22e7171bSAlfredo Cardigliano 		if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
573*22e7171bSAlfredo Cardigliano 			rss_types |= IONIC_RSS_TYPE_IPV6_TCP;
574*22e7171bSAlfredo Cardigliano 		if (rss_conf->rss_hf & ETH_RSS_NONFRAG_IPV6_UDP)
575*22e7171bSAlfredo Cardigliano 			rss_types |= IONIC_RSS_TYPE_IPV6_UDP;
576*22e7171bSAlfredo Cardigliano 
577*22e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, rss_types, key, NULL);
578*22e7171bSAlfredo Cardigliano 	}
579*22e7171bSAlfredo Cardigliano 
580*22e7171bSAlfredo Cardigliano 	return 0;
581*22e7171bSAlfredo Cardigliano }
582*22e7171bSAlfredo Cardigliano 
583*22e7171bSAlfredo Cardigliano static int
584598f6726SAlfredo Cardigliano ionic_dev_configure(struct rte_eth_dev *eth_dev)
585598f6726SAlfredo Cardigliano {
586598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
587598f6726SAlfredo Cardigliano 	int err;
588598f6726SAlfredo Cardigliano 
589598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
590598f6726SAlfredo Cardigliano 
591598f6726SAlfredo Cardigliano 	err = ionic_lif_configure(lif);
592598f6726SAlfredo Cardigliano 	if (err) {
593598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot configure LIF: %d", err);
594598f6726SAlfredo Cardigliano 		return err;
595598f6726SAlfredo Cardigliano 	}
596598f6726SAlfredo Cardigliano 
597598f6726SAlfredo Cardigliano 	return 0;
598598f6726SAlfredo Cardigliano }
599598f6726SAlfredo Cardigliano 
600598f6726SAlfredo Cardigliano static inline uint32_t
601598f6726SAlfredo Cardigliano ionic_parse_link_speeds(uint16_t link_speeds)
602598f6726SAlfredo Cardigliano {
603598f6726SAlfredo Cardigliano 	if (link_speeds & ETH_LINK_SPEED_100G)
604598f6726SAlfredo Cardigliano 		return 100000;
605598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_50G)
606598f6726SAlfredo Cardigliano 		return 50000;
607598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_40G)
608598f6726SAlfredo Cardigliano 		return 40000;
609598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_25G)
610598f6726SAlfredo Cardigliano 		return 25000;
611598f6726SAlfredo Cardigliano 	else if (link_speeds & ETH_LINK_SPEED_10G)
612598f6726SAlfredo Cardigliano 		return 10000;
613598f6726SAlfredo Cardigliano 	else
614598f6726SAlfredo Cardigliano 		return 0;
615598f6726SAlfredo Cardigliano }
616598f6726SAlfredo Cardigliano 
617598f6726SAlfredo Cardigliano /*
618598f6726SAlfredo Cardigliano  * Configure device link speed and setup link.
619598f6726SAlfredo Cardigliano  * It returns 0 on success.
620598f6726SAlfredo Cardigliano  */
621598f6726SAlfredo Cardigliano static int
622598f6726SAlfredo Cardigliano ionic_dev_start(struct rte_eth_dev *eth_dev)
623598f6726SAlfredo Cardigliano {
624598f6726SAlfredo Cardigliano 	struct rte_eth_conf *dev_conf = &eth_dev->data->dev_conf;
625598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
626598f6726SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
627598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
628598f6726SAlfredo Cardigliano 	uint32_t allowed_speeds;
629598f6726SAlfredo Cardigliano 	int err;
630598f6726SAlfredo Cardigliano 
631598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
632598f6726SAlfredo Cardigliano 
633598f6726SAlfredo Cardigliano 	allowed_speeds =
634598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_FIXED |
635598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_10G |
636598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_25G |
637598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_40G |
638598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_50G |
639598f6726SAlfredo Cardigliano 		ETH_LINK_SPEED_100G;
640598f6726SAlfredo Cardigliano 
641598f6726SAlfredo Cardigliano 	if (dev_conf->link_speeds & ~allowed_speeds) {
642598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Invalid link setting");
643598f6726SAlfredo Cardigliano 		return -EINVAL;
644598f6726SAlfredo Cardigliano 	}
645598f6726SAlfredo Cardigliano 
646598f6726SAlfredo Cardigliano 	err = ionic_lif_start(lif);
647598f6726SAlfredo Cardigliano 	if (err) {
648598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot start LIF: %d", err);
649598f6726SAlfredo Cardigliano 		return err;
650598f6726SAlfredo Cardigliano 	}
651598f6726SAlfredo Cardigliano 
652598f6726SAlfredo Cardigliano 	if (eth_dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
653598f6726SAlfredo Cardigliano 		uint32_t speed = ionic_parse_link_speeds(dev_conf->link_speeds);
654598f6726SAlfredo Cardigliano 
655598f6726SAlfredo Cardigliano 		if (speed)
656598f6726SAlfredo Cardigliano 			ionic_dev_cmd_port_speed(idev, speed);
657598f6726SAlfredo Cardigliano 	}
658598f6726SAlfredo Cardigliano 
659598f6726SAlfredo Cardigliano 	ionic_dev_link_update(eth_dev, 0);
660598f6726SAlfredo Cardigliano 
661598f6726SAlfredo Cardigliano 	return 0;
662598f6726SAlfredo Cardigliano }
663598f6726SAlfredo Cardigliano 
664598f6726SAlfredo Cardigliano /*
665598f6726SAlfredo Cardigliano  * Stop device: disable rx and tx functions to allow for reconfiguring.
666598f6726SAlfredo Cardigliano  */
667598f6726SAlfredo Cardigliano static void
668598f6726SAlfredo Cardigliano ionic_dev_stop(struct rte_eth_dev *eth_dev)
669598f6726SAlfredo Cardigliano {
670598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
671598f6726SAlfredo Cardigliano 	int err;
672598f6726SAlfredo Cardigliano 
673598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
674598f6726SAlfredo Cardigliano 
675598f6726SAlfredo Cardigliano 	err = ionic_lif_stop(lif);
676598f6726SAlfredo Cardigliano 	if (err)
677598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
678598f6726SAlfredo Cardigliano }
679598f6726SAlfredo Cardigliano 
680598f6726SAlfredo Cardigliano /*
681598f6726SAlfredo Cardigliano  * Reset and stop device.
682598f6726SAlfredo Cardigliano  */
683598f6726SAlfredo Cardigliano static void
684598f6726SAlfredo Cardigliano ionic_dev_close(struct rte_eth_dev *eth_dev)
685598f6726SAlfredo Cardigliano {
686598f6726SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
687598f6726SAlfredo Cardigliano 	int err;
688598f6726SAlfredo Cardigliano 
689598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
690598f6726SAlfredo Cardigliano 
691598f6726SAlfredo Cardigliano 	err = ionic_lif_stop(lif);
692598f6726SAlfredo Cardigliano 	if (err) {
693598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
694598f6726SAlfredo Cardigliano 		return;
695598f6726SAlfredo Cardigliano 	}
696598f6726SAlfredo Cardigliano 
697598f6726SAlfredo Cardigliano 	err = eth_ionic_dev_uninit(eth_dev);
698598f6726SAlfredo Cardigliano 	if (err) {
699598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot destroy LIF: %d", err);
700598f6726SAlfredo Cardigliano 		return;
701598f6726SAlfredo Cardigliano 	}
702598f6726SAlfredo Cardigliano }
703598f6726SAlfredo Cardigliano 
704598f6726SAlfredo Cardigliano static int
705669c8de6SAlfredo Cardigliano eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
706669c8de6SAlfredo Cardigliano {
707669c8de6SAlfredo Cardigliano 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
708669c8de6SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
709669c8de6SAlfredo Cardigliano 	struct ionic_adapter *adapter = (struct ionic_adapter *)init_params;
710669c8de6SAlfredo Cardigliano 	int err;
711669c8de6SAlfredo Cardigliano 
712669c8de6SAlfredo Cardigliano 	IONIC_PRINT_CALL();
713669c8de6SAlfredo Cardigliano 
714669c8de6SAlfredo Cardigliano 	eth_dev->dev_ops = &ionic_eth_dev_ops;
715a27d9013SAlfredo Cardigliano 	eth_dev->rx_pkt_burst = &ionic_recv_pkts;
716a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_burst = &ionic_xmit_pkts;
717a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_prepare = &ionic_prep_pkts;
718669c8de6SAlfredo Cardigliano 
719669c8de6SAlfredo Cardigliano 	/* Multi-process not supported, primary does initialization anyway */
720669c8de6SAlfredo Cardigliano 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
721669c8de6SAlfredo Cardigliano 		return 0;
722669c8de6SAlfredo Cardigliano 
723669c8de6SAlfredo Cardigliano 	rte_eth_copy_pci_info(eth_dev, pci_dev);
724669c8de6SAlfredo Cardigliano 
725669c8de6SAlfredo Cardigliano 	lif->index = adapter->nlifs;
726669c8de6SAlfredo Cardigliano 	lif->eth_dev = eth_dev;
727669c8de6SAlfredo Cardigliano 	lif->adapter = adapter;
728669c8de6SAlfredo Cardigliano 	adapter->lifs[adapter->nlifs] = lif;
729669c8de6SAlfredo Cardigliano 
730598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Up to %u MAC addresses supported",
731598f6726SAlfredo Cardigliano 		adapter->max_mac_addrs);
732598f6726SAlfredo Cardigliano 
733598f6726SAlfredo Cardigliano 	/* Allocate memory for storing MAC addresses */
734598f6726SAlfredo Cardigliano 	eth_dev->data->mac_addrs = rte_zmalloc("ionic",
735598f6726SAlfredo Cardigliano 		RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs, 0);
736598f6726SAlfredo Cardigliano 
737598f6726SAlfredo Cardigliano 	if (eth_dev->data->mac_addrs == NULL) {
738598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to allocate %u bytes needed to "
739598f6726SAlfredo Cardigliano 			"store MAC addresses",
740598f6726SAlfredo Cardigliano 			RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs);
741598f6726SAlfredo Cardigliano 		err = -ENOMEM;
742598f6726SAlfredo Cardigliano 		goto err;
743598f6726SAlfredo Cardigliano 	}
744598f6726SAlfredo Cardigliano 
745669c8de6SAlfredo Cardigliano 	err = ionic_lif_alloc(lif);
746669c8de6SAlfredo Cardigliano 	if (err) {
747669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate LIFs: %d, aborting",
748669c8de6SAlfredo Cardigliano 			err);
749669c8de6SAlfredo Cardigliano 		goto err;
750669c8de6SAlfredo Cardigliano 	}
751669c8de6SAlfredo Cardigliano 
752669c8de6SAlfredo Cardigliano 	err = ionic_lif_init(lif);
753669c8de6SAlfredo Cardigliano 	if (err) {
754669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot init LIFs: %d, aborting", err);
755669c8de6SAlfredo Cardigliano 		goto err_free_lif;
756669c8de6SAlfredo Cardigliano 	}
757669c8de6SAlfredo Cardigliano 
758598f6726SAlfredo Cardigliano 	/* Copy the MAC address */
759598f6726SAlfredo Cardigliano 	rte_ether_addr_copy((struct rte_ether_addr *)lif->mac_addr,
760598f6726SAlfredo Cardigliano 		&eth_dev->data->mac_addrs[0]);
761598f6726SAlfredo Cardigliano 
762669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Port %u initialized", eth_dev->data->port_id);
763669c8de6SAlfredo Cardigliano 
764669c8de6SAlfredo Cardigliano 	return 0;
765669c8de6SAlfredo Cardigliano 
766669c8de6SAlfredo Cardigliano err_free_lif:
767669c8de6SAlfredo Cardigliano 	ionic_lif_free(lif);
768669c8de6SAlfredo Cardigliano err:
769669c8de6SAlfredo Cardigliano 	return err;
770669c8de6SAlfredo Cardigliano }
771669c8de6SAlfredo Cardigliano 
772669c8de6SAlfredo Cardigliano static int
773669c8de6SAlfredo Cardigliano eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev)
774669c8de6SAlfredo Cardigliano {
775669c8de6SAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
776669c8de6SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
777669c8de6SAlfredo Cardigliano 
778669c8de6SAlfredo Cardigliano 	IONIC_PRINT_CALL();
779669c8de6SAlfredo Cardigliano 
780669c8de6SAlfredo Cardigliano 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
781669c8de6SAlfredo Cardigliano 		return 0;
782669c8de6SAlfredo Cardigliano 
783669c8de6SAlfredo Cardigliano 	adapter->lifs[lif->index] = NULL;
784669c8de6SAlfredo Cardigliano 
785669c8de6SAlfredo Cardigliano 	ionic_lif_deinit(lif);
786669c8de6SAlfredo Cardigliano 	ionic_lif_free(lif);
787669c8de6SAlfredo Cardigliano 
788669c8de6SAlfredo Cardigliano 	eth_dev->dev_ops = NULL;
789a27d9013SAlfredo Cardigliano 	eth_dev->rx_pkt_burst = NULL;
790a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_burst = NULL;
791a27d9013SAlfredo Cardigliano 	eth_dev->tx_pkt_prepare = NULL;
792669c8de6SAlfredo Cardigliano 
793669c8de6SAlfredo Cardigliano 	return 0;
794669c8de6SAlfredo Cardigliano }
795669c8de6SAlfredo Cardigliano 
7965ef51809SAlfredo Cardigliano static int
79727b942c8SAlfredo Cardigliano ionic_configure_intr(struct ionic_adapter *adapter)
79827b942c8SAlfredo Cardigliano {
79927b942c8SAlfredo Cardigliano 	struct rte_pci_device *pci_dev = adapter->pci_dev;
80027b942c8SAlfredo Cardigliano 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
80127b942c8SAlfredo Cardigliano 	int err;
80227b942c8SAlfredo Cardigliano 
80327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring %u intrs", adapter->nintrs);
80427b942c8SAlfredo Cardigliano 
80527b942c8SAlfredo Cardigliano 	if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
80627b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Fail to create eventfd");
80727b942c8SAlfredo Cardigliano 		return -1;
80827b942c8SAlfredo Cardigliano 	}
80927b942c8SAlfredo Cardigliano 
81027b942c8SAlfredo Cardigliano 	if (rte_intr_dp_is_en(intr_handle))
81127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
81227b942c8SAlfredo Cardigliano 			"Packet I/O interrupt on datapath is enabled");
81327b942c8SAlfredo Cardigliano 
81427b942c8SAlfredo Cardigliano 	if (!intr_handle->intr_vec) {
81527b942c8SAlfredo Cardigliano 		intr_handle->intr_vec = rte_zmalloc("intr_vec",
81627b942c8SAlfredo Cardigliano 			adapter->nintrs * sizeof(int), 0);
81727b942c8SAlfredo Cardigliano 
81827b942c8SAlfredo Cardigliano 		if (!intr_handle->intr_vec) {
81927b942c8SAlfredo Cardigliano 			IONIC_PRINT(ERR, "Failed to allocate %u vectors",
82027b942c8SAlfredo Cardigliano 				adapter->nintrs);
82127b942c8SAlfredo Cardigliano 			return -ENOMEM;
82227b942c8SAlfredo Cardigliano 		}
82327b942c8SAlfredo Cardigliano 	}
82427b942c8SAlfredo Cardigliano 
82527b942c8SAlfredo Cardigliano 	err = rte_intr_callback_register(intr_handle,
82627b942c8SAlfredo Cardigliano 		ionic_dev_interrupt_handler,
82727b942c8SAlfredo Cardigliano 		adapter);
82827b942c8SAlfredo Cardigliano 
82927b942c8SAlfredo Cardigliano 	if (err) {
83027b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR,
83127b942c8SAlfredo Cardigliano 			"Failure registering interrupts handler (%d)",
83227b942c8SAlfredo Cardigliano 			err);
83327b942c8SAlfredo Cardigliano 		return err;
83427b942c8SAlfredo Cardigliano 	}
83527b942c8SAlfredo Cardigliano 
83627b942c8SAlfredo Cardigliano 	/* enable intr mapping */
83727b942c8SAlfredo Cardigliano 	err = rte_intr_enable(intr_handle);
83827b942c8SAlfredo Cardigliano 
83927b942c8SAlfredo Cardigliano 	if (err) {
84027b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
84127b942c8SAlfredo Cardigliano 		return err;
84227b942c8SAlfredo Cardigliano 	}
84327b942c8SAlfredo Cardigliano 
84427b942c8SAlfredo Cardigliano 	return 0;
84527b942c8SAlfredo Cardigliano }
84627b942c8SAlfredo Cardigliano 
84727b942c8SAlfredo Cardigliano static void
84827b942c8SAlfredo Cardigliano ionic_unconfigure_intr(struct ionic_adapter *adapter)
84927b942c8SAlfredo Cardigliano {
85027b942c8SAlfredo Cardigliano 	struct rte_pci_device *pci_dev = adapter->pci_dev;
85127b942c8SAlfredo Cardigliano 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
85227b942c8SAlfredo Cardigliano 
85327b942c8SAlfredo Cardigliano 	rte_intr_disable(intr_handle);
85427b942c8SAlfredo Cardigliano 
85527b942c8SAlfredo Cardigliano 	rte_intr_callback_unregister(intr_handle,
85627b942c8SAlfredo Cardigliano 		ionic_dev_interrupt_handler,
85727b942c8SAlfredo Cardigliano 		adapter);
85827b942c8SAlfredo Cardigliano }
85927b942c8SAlfredo Cardigliano 
86027b942c8SAlfredo Cardigliano static int
8615ef51809SAlfredo Cardigliano eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
8625ef51809SAlfredo Cardigliano 		struct rte_pci_device *pci_dev)
8635ef51809SAlfredo Cardigliano {
864669c8de6SAlfredo Cardigliano 	char name[RTE_ETH_NAME_MAX_LEN];
8655ef51809SAlfredo Cardigliano 	struct rte_mem_resource *resource;
8665ef51809SAlfredo Cardigliano 	struct ionic_adapter *adapter;
8675ef51809SAlfredo Cardigliano 	struct ionic_hw *hw;
8685ef51809SAlfredo Cardigliano 	unsigned long i;
8695ef51809SAlfredo Cardigliano 	int err;
8705ef51809SAlfredo Cardigliano 
8715ef51809SAlfredo Cardigliano 	/* Check structs (trigger error at compilation time) */
8725ef51809SAlfredo Cardigliano 	ionic_struct_size_checks();
8735ef51809SAlfredo Cardigliano 
8745ef51809SAlfredo Cardigliano 	/* Multi-process not supported */
8755ef51809SAlfredo Cardigliano 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
8765ef51809SAlfredo Cardigliano 		err = -EPERM;
8775ef51809SAlfredo Cardigliano 		goto err;
8785ef51809SAlfredo Cardigliano 	}
8795ef51809SAlfredo Cardigliano 
8805ef51809SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Initializing device %s",
8815ef51809SAlfredo Cardigliano 		pci_dev->device.name);
8825ef51809SAlfredo Cardigliano 
8835ef51809SAlfredo Cardigliano 	adapter = rte_zmalloc("ionic", sizeof(*adapter), 0);
8845ef51809SAlfredo Cardigliano 	if (!adapter) {
8855ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "OOM");
8865ef51809SAlfredo Cardigliano 		err = -ENOMEM;
8875ef51809SAlfredo Cardigliano 		goto err;
8885ef51809SAlfredo Cardigliano 	}
8895ef51809SAlfredo Cardigliano 
8905ef51809SAlfredo Cardigliano 	adapter->pci_dev = pci_dev;
8915ef51809SAlfredo Cardigliano 	hw = &adapter->hw;
8925ef51809SAlfredo Cardigliano 
8935ef51809SAlfredo Cardigliano 	hw->device_id = pci_dev->id.device_id;
8945ef51809SAlfredo Cardigliano 	hw->vendor_id = pci_dev->id.vendor_id;
8955ef51809SAlfredo Cardigliano 
8965ef51809SAlfredo Cardigliano 	err = ionic_init_mac(hw);
8975ef51809SAlfredo Cardigliano 	if (err != 0) {
8985ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Mac init failed: %d", err);
8995ef51809SAlfredo Cardigliano 		err = -EIO;
9005ef51809SAlfredo Cardigliano 		goto err_free_adapter;
9015ef51809SAlfredo Cardigliano 	}
9025ef51809SAlfredo Cardigliano 
9035ef51809SAlfredo Cardigliano 	adapter->is_mgmt_nic = (pci_dev->id.device_id == IONIC_DEV_ID_ETH_MGMT);
9045ef51809SAlfredo Cardigliano 
9055ef51809SAlfredo Cardigliano 	adapter->num_bars = 0;
9065ef51809SAlfredo Cardigliano 	for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
9075ef51809SAlfredo Cardigliano 		resource = &pci_dev->mem_resource[i];
9085ef51809SAlfredo Cardigliano 		if (resource->phys_addr == 0 || resource->len == 0)
9095ef51809SAlfredo Cardigliano 			continue;
9105ef51809SAlfredo Cardigliano 		adapter->bars[adapter->num_bars].vaddr = resource->addr;
9115ef51809SAlfredo Cardigliano 		adapter->bars[adapter->num_bars].bus_addr = resource->phys_addr;
9125ef51809SAlfredo Cardigliano 		adapter->bars[adapter->num_bars].len = resource->len;
9135ef51809SAlfredo Cardigliano 		adapter->num_bars++;
9145ef51809SAlfredo Cardigliano 	}
9155ef51809SAlfredo Cardigliano 
9165ef51809SAlfredo Cardigliano 	/* Discover ionic dev resources */
9175ef51809SAlfredo Cardigliano 
9185ef51809SAlfredo Cardigliano 	err = ionic_setup(adapter);
9195ef51809SAlfredo Cardigliano 	if (err) {
9205ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot setup device: %d, aborting", err);
9215ef51809SAlfredo Cardigliano 		goto err_free_adapter;
9225ef51809SAlfredo Cardigliano 	}
9235ef51809SAlfredo Cardigliano 
9245ef51809SAlfredo Cardigliano 	err = ionic_identify(adapter);
9255ef51809SAlfredo Cardigliano 	if (err) {
9265ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot identify device: %d, aborting",
9275ef51809SAlfredo Cardigliano 			err);
9285ef51809SAlfredo Cardigliano 		goto err_free_adapter;
9295ef51809SAlfredo Cardigliano 	}
9305ef51809SAlfredo Cardigliano 
9315ef51809SAlfredo Cardigliano 	err = ionic_init(adapter);
9325ef51809SAlfredo Cardigliano 	if (err) {
9335ef51809SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot init device: %d, aborting", err);
9345ef51809SAlfredo Cardigliano 		goto err_free_adapter;
9355ef51809SAlfredo Cardigliano 	}
9365ef51809SAlfredo Cardigliano 
93723bf4ddbSAlfredo Cardigliano 	/* Configure the ports */
93823bf4ddbSAlfredo Cardigliano 	err = ionic_port_identify(adapter);
93923bf4ddbSAlfredo Cardigliano 	if (err) {
94023bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot identify port: %d, aborting",
94123bf4ddbSAlfredo Cardigliano 			err);
94223bf4ddbSAlfredo Cardigliano 		goto err_free_adapter;
94323bf4ddbSAlfredo Cardigliano 	}
94423bf4ddbSAlfredo Cardigliano 
94523bf4ddbSAlfredo Cardigliano 	err = ionic_port_init(adapter);
94623bf4ddbSAlfredo Cardigliano 	if (err) {
94723bf4ddbSAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot init port: %d, aborting", err);
94823bf4ddbSAlfredo Cardigliano 		goto err_free_adapter;
94923bf4ddbSAlfredo Cardigliano 	}
95023bf4ddbSAlfredo Cardigliano 
951669c8de6SAlfredo Cardigliano 	/* Configure LIFs */
952669c8de6SAlfredo Cardigliano 	err = ionic_lif_identify(adapter);
953669c8de6SAlfredo Cardigliano 	if (err) {
954669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot identify lif: %d, aborting", err);
955669c8de6SAlfredo Cardigliano 		goto err_free_adapter;
956669c8de6SAlfredo Cardigliano 	}
957669c8de6SAlfredo Cardigliano 
958669c8de6SAlfredo Cardigliano 	/* Allocate and init LIFs */
959669c8de6SAlfredo Cardigliano 	err = ionic_lifs_size(adapter);
960669c8de6SAlfredo Cardigliano 	if (err) {
961669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot size LIFs: %d, aborting", err);
962669c8de6SAlfredo Cardigliano 		goto err_free_adapter;
963669c8de6SAlfredo Cardigliano 	}
964669c8de6SAlfredo Cardigliano 
965598f6726SAlfredo Cardigliano 	adapter->max_mac_addrs = adapter->ident.lif.eth.max_ucast_filters;
966598f6726SAlfredo Cardigliano 
967669c8de6SAlfredo Cardigliano 	adapter->nlifs = 0;
968669c8de6SAlfredo Cardigliano 	for (i = 0; i < adapter->ident.dev.nlifs; i++) {
969669c8de6SAlfredo Cardigliano 		snprintf(name, sizeof(name), "net_%s_lif_%lu",
970669c8de6SAlfredo Cardigliano 			pci_dev->device.name, i);
971669c8de6SAlfredo Cardigliano 
972669c8de6SAlfredo Cardigliano 		err = rte_eth_dev_create(&pci_dev->device, name,
973669c8de6SAlfredo Cardigliano 			sizeof(struct ionic_lif),
974669c8de6SAlfredo Cardigliano 			NULL, NULL,
975669c8de6SAlfredo Cardigliano 			eth_ionic_dev_init, adapter);
976669c8de6SAlfredo Cardigliano 		if (err) {
977669c8de6SAlfredo Cardigliano 			IONIC_PRINT(ERR, "Cannot create eth device for "
978669c8de6SAlfredo Cardigliano 				"ionic lif %s", name);
979669c8de6SAlfredo Cardigliano 			break;
980669c8de6SAlfredo Cardigliano 		}
981669c8de6SAlfredo Cardigliano 
982669c8de6SAlfredo Cardigliano 		adapter->nlifs++;
983669c8de6SAlfredo Cardigliano 	}
984669c8de6SAlfredo Cardigliano 
98527b942c8SAlfredo Cardigliano 	err = ionic_configure_intr(adapter);
98627b942c8SAlfredo Cardigliano 
98727b942c8SAlfredo Cardigliano 	if (err) {
98827b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failed to configure interrupts");
98927b942c8SAlfredo Cardigliano 		goto err_free_adapter;
99027b942c8SAlfredo Cardigliano 	}
99127b942c8SAlfredo Cardigliano 
9925ef51809SAlfredo Cardigliano 	return 0;
9935ef51809SAlfredo Cardigliano 
9945ef51809SAlfredo Cardigliano err_free_adapter:
9955ef51809SAlfredo Cardigliano 	rte_free(adapter);
9965ef51809SAlfredo Cardigliano err:
9975ef51809SAlfredo Cardigliano 	return err;
9985ef51809SAlfredo Cardigliano }
9995ef51809SAlfredo Cardigliano 
10005ef51809SAlfredo Cardigliano static int
10015ef51809SAlfredo Cardigliano eth_ionic_pci_remove(struct rte_pci_device *pci_dev __rte_unused)
10025ef51809SAlfredo Cardigliano {
1003669c8de6SAlfredo Cardigliano 	char name[RTE_ETH_NAME_MAX_LEN];
1004669c8de6SAlfredo Cardigliano 	struct ionic_adapter *adapter = NULL;
1005669c8de6SAlfredo Cardigliano 	struct rte_eth_dev *eth_dev;
1006669c8de6SAlfredo Cardigliano 	struct ionic_lif *lif;
1007669c8de6SAlfredo Cardigliano 	uint32_t i;
1008669c8de6SAlfredo Cardigliano 
1009669c8de6SAlfredo Cardigliano 	/* Adapter lookup is using (the first) eth_dev name */
1010669c8de6SAlfredo Cardigliano 	snprintf(name, sizeof(name), "net_%s_lif_0",
1011669c8de6SAlfredo Cardigliano 		pci_dev->device.name);
1012669c8de6SAlfredo Cardigliano 
1013669c8de6SAlfredo Cardigliano 	eth_dev = rte_eth_dev_allocated(name);
1014669c8de6SAlfredo Cardigliano 	if (eth_dev) {
1015669c8de6SAlfredo Cardigliano 		lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
1016669c8de6SAlfredo Cardigliano 		adapter = lif->adapter;
1017669c8de6SAlfredo Cardigliano 	}
1018669c8de6SAlfredo Cardigliano 
1019669c8de6SAlfredo Cardigliano 	if (adapter) {
102027b942c8SAlfredo Cardigliano 		ionic_unconfigure_intr(adapter);
102127b942c8SAlfredo Cardigliano 
1022669c8de6SAlfredo Cardigliano 		for (i = 0; i < adapter->nlifs; i++) {
1023669c8de6SAlfredo Cardigliano 			lif = adapter->lifs[i];
1024669c8de6SAlfredo Cardigliano 			rte_eth_dev_destroy(lif->eth_dev, eth_ionic_dev_uninit);
1025669c8de6SAlfredo Cardigliano 		}
1026669c8de6SAlfredo Cardigliano 
1027669c8de6SAlfredo Cardigliano 		rte_free(adapter);
1028669c8de6SAlfredo Cardigliano 	}
1029669c8de6SAlfredo Cardigliano 
10305ef51809SAlfredo Cardigliano 	return 0;
10315ef51809SAlfredo Cardigliano }
10325ef51809SAlfredo Cardigliano 
10335ef51809SAlfredo Cardigliano static struct rte_pci_driver rte_ionic_pmd = {
10345ef51809SAlfredo Cardigliano 	.id_table = pci_id_ionic_map,
10355ef51809SAlfredo Cardigliano 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
10365ef51809SAlfredo Cardigliano 	.probe = eth_ionic_pci_probe,
10375ef51809SAlfredo Cardigliano 	.remove = eth_ionic_pci_remove,
10385ef51809SAlfredo Cardigliano };
10395ef51809SAlfredo Cardigliano 
10405ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI(net_ionic, rte_ionic_pmd);
10415ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI_TABLE(net_ionic, pci_id_ionic_map);
10425ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_KMOD_DEP(net_ionic, "* igb_uio | uio_pci_generic | vfio-pci");
10435ef51809SAlfredo Cardigliano 
10447c125393SAlfredo Cardigliano RTE_INIT(ionic_init_log)
10457c125393SAlfredo Cardigliano {
10467c125393SAlfredo Cardigliano 	ionic_logtype = rte_log_register("pmd.net.ionic");
10477c125393SAlfredo Cardigliano 	if (ionic_logtype >= 0)
10487c125393SAlfredo Cardigliano 		rte_log_set_level(ionic_logtype, RTE_LOG_NOTICE);
10497c125393SAlfredo Cardigliano }
1050