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 = ð_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 = ð_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 ð_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