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" 18669c8de6SAlfredo Cardigliano 19669c8de6SAlfredo Cardigliano static int eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params); 20669c8de6SAlfredo Cardigliano static int eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev); 21598f6726SAlfredo Cardigliano static int ionic_dev_info_get(struct rte_eth_dev *eth_dev, 22598f6726SAlfredo Cardigliano struct rte_eth_dev_info *dev_info); 23598f6726SAlfredo Cardigliano static int ionic_dev_configure(struct rte_eth_dev *dev); 24598f6726SAlfredo Cardigliano static int ionic_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); 25598f6726SAlfredo Cardigliano static int ionic_dev_start(struct rte_eth_dev *dev); 26598f6726SAlfredo Cardigliano static void ionic_dev_stop(struct rte_eth_dev *dev); 27598f6726SAlfredo Cardigliano static void ionic_dev_close(struct rte_eth_dev *dev); 28598f6726SAlfredo Cardigliano static int ionic_dev_set_link_up(struct rte_eth_dev *dev); 29598f6726SAlfredo Cardigliano static int ionic_dev_set_link_down(struct rte_eth_dev *dev); 30598f6726SAlfredo Cardigliano static int ionic_dev_link_update(struct rte_eth_dev *eth_dev, 31598f6726SAlfredo Cardigliano int wait_to_complete); 32*ec15c66bSAlfredo Cardigliano static int ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev, 33*ec15c66bSAlfredo Cardigliano struct rte_eth_fc_conf *fc_conf); 34*ec15c66bSAlfredo Cardigliano static int ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev, 35*ec15c66bSAlfredo Cardigliano struct rte_eth_fc_conf *fc_conf); 367c125393SAlfredo Cardigliano 377c125393SAlfredo Cardigliano int ionic_logtype; 387c125393SAlfredo Cardigliano 395ef51809SAlfredo Cardigliano static const struct rte_pci_id pci_id_ionic_map[] = { 405ef51809SAlfredo Cardigliano { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) }, 415ef51809SAlfredo Cardigliano { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) }, 425ef51809SAlfredo Cardigliano { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) }, 435ef51809SAlfredo Cardigliano { .vendor_id = 0, /* sentinel */ }, 445ef51809SAlfredo Cardigliano }; 455ef51809SAlfredo Cardigliano 46669c8de6SAlfredo Cardigliano static const struct eth_dev_ops ionic_eth_dev_ops = { 47598f6726SAlfredo Cardigliano .dev_infos_get = ionic_dev_info_get, 48598f6726SAlfredo Cardigliano .dev_configure = ionic_dev_configure, 49598f6726SAlfredo Cardigliano .mtu_set = ionic_dev_mtu_set, 50598f6726SAlfredo Cardigliano .dev_start = ionic_dev_start, 51598f6726SAlfredo Cardigliano .dev_stop = ionic_dev_stop, 52598f6726SAlfredo Cardigliano .dev_close = ionic_dev_close, 53598f6726SAlfredo Cardigliano .link_update = ionic_dev_link_update, 54598f6726SAlfredo Cardigliano .dev_set_link_up = ionic_dev_set_link_up, 55598f6726SAlfredo Cardigliano .dev_set_link_down = ionic_dev_set_link_down, 5654fe083fSAlfredo Cardigliano .mac_addr_add = ionic_dev_add_mac, 5754fe083fSAlfredo Cardigliano .mac_addr_remove = ionic_dev_remove_mac, 5854fe083fSAlfredo Cardigliano .mac_addr_set = ionic_dev_set_mac, 5954fe083fSAlfredo Cardigliano .vlan_filter_set = ionic_dev_vlan_filter_set, 6054fe083fSAlfredo Cardigliano .promiscuous_enable = ionic_dev_promiscuous_enable, 6154fe083fSAlfredo Cardigliano .promiscuous_disable = ionic_dev_promiscuous_disable, 6254fe083fSAlfredo Cardigliano .allmulticast_enable = ionic_dev_allmulticast_enable, 6354fe083fSAlfredo Cardigliano .allmulticast_disable = ionic_dev_allmulticast_disable, 64*ec15c66bSAlfredo Cardigliano .flow_ctrl_get = ionic_flow_ctrl_get, 65*ec15c66bSAlfredo Cardigliano .flow_ctrl_set = ionic_flow_ctrl_set, 66669c8de6SAlfredo Cardigliano }; 67669c8de6SAlfredo Cardigliano 68598f6726SAlfredo Cardigliano /* 69598f6726SAlfredo Cardigliano * Set device link up, enable tx. 70598f6726SAlfredo Cardigliano */ 71598f6726SAlfredo Cardigliano static int 72598f6726SAlfredo Cardigliano ionic_dev_set_link_up(struct rte_eth_dev *eth_dev) 73598f6726SAlfredo Cardigliano { 74598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 75598f6726SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 76598f6726SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 77598f6726SAlfredo Cardigliano int err; 78598f6726SAlfredo Cardigliano 79598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 80598f6726SAlfredo Cardigliano 81598f6726SAlfredo Cardigliano ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP); 82598f6726SAlfredo Cardigliano 83598f6726SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 84598f6726SAlfredo Cardigliano if (err) { 85598f6726SAlfredo Cardigliano IONIC_PRINT(WARNING, "Failed to bring port UP"); 86598f6726SAlfredo Cardigliano return err; 87598f6726SAlfredo Cardigliano } 88598f6726SAlfredo Cardigliano 89598f6726SAlfredo Cardigliano return 0; 90598f6726SAlfredo Cardigliano } 91598f6726SAlfredo Cardigliano 92598f6726SAlfredo Cardigliano /* 93598f6726SAlfredo Cardigliano * Set device link down, disable tx. 94598f6726SAlfredo Cardigliano */ 95598f6726SAlfredo Cardigliano static int 96598f6726SAlfredo Cardigliano ionic_dev_set_link_down(struct rte_eth_dev *eth_dev) 97598f6726SAlfredo Cardigliano { 98598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 99598f6726SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 100598f6726SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 101598f6726SAlfredo Cardigliano int err; 102598f6726SAlfredo Cardigliano 103598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 104598f6726SAlfredo Cardigliano 105598f6726SAlfredo Cardigliano ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_DOWN); 106598f6726SAlfredo Cardigliano 107598f6726SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 108598f6726SAlfredo Cardigliano if (err) { 109598f6726SAlfredo Cardigliano IONIC_PRINT(WARNING, "Failed to bring port DOWN"); 110598f6726SAlfredo Cardigliano return err; 111598f6726SAlfredo Cardigliano } 112598f6726SAlfredo Cardigliano 113598f6726SAlfredo Cardigliano return 0; 114598f6726SAlfredo Cardigliano } 115598f6726SAlfredo Cardigliano 116598f6726SAlfredo Cardigliano static int 117598f6726SAlfredo Cardigliano ionic_dev_link_update(struct rte_eth_dev *eth_dev, 118598f6726SAlfredo Cardigliano int wait_to_complete __rte_unused) 119598f6726SAlfredo Cardigliano { 120598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 121598f6726SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 122598f6726SAlfredo Cardigliano struct rte_eth_link link; 123598f6726SAlfredo Cardigliano 124598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 125598f6726SAlfredo Cardigliano 126598f6726SAlfredo Cardigliano /* Initialize */ 127598f6726SAlfredo Cardigliano memset(&link, 0, sizeof(link)); 128598f6726SAlfredo Cardigliano link.link_autoneg = ETH_LINK_AUTONEG; 129598f6726SAlfredo Cardigliano 130598f6726SAlfredo Cardigliano if (!adapter->link_up) { 131598f6726SAlfredo Cardigliano /* Interface is down */ 132598f6726SAlfredo Cardigliano link.link_status = ETH_LINK_DOWN; 133598f6726SAlfredo Cardigliano link.link_duplex = ETH_LINK_HALF_DUPLEX; 134598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_NONE; 135598f6726SAlfredo Cardigliano } else { 136598f6726SAlfredo Cardigliano /* Interface is up */ 137598f6726SAlfredo Cardigliano link.link_status = ETH_LINK_UP; 138598f6726SAlfredo Cardigliano link.link_duplex = ETH_LINK_FULL_DUPLEX; 139598f6726SAlfredo Cardigliano switch (adapter->link_speed) { 140598f6726SAlfredo Cardigliano case 10000: 141598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_10G; 142598f6726SAlfredo Cardigliano break; 143598f6726SAlfredo Cardigliano case 25000: 144598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_25G; 145598f6726SAlfredo Cardigliano break; 146598f6726SAlfredo Cardigliano case 40000: 147598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_40G; 148598f6726SAlfredo Cardigliano break; 149598f6726SAlfredo Cardigliano case 50000: 150598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_50G; 151598f6726SAlfredo Cardigliano break; 152598f6726SAlfredo Cardigliano case 100000: 153598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_100G; 154598f6726SAlfredo Cardigliano break; 155598f6726SAlfredo Cardigliano default: 156598f6726SAlfredo Cardigliano link.link_speed = ETH_SPEED_NUM_NONE; 157598f6726SAlfredo Cardigliano break; 158598f6726SAlfredo Cardigliano } 159598f6726SAlfredo Cardigliano } 160598f6726SAlfredo Cardigliano 161598f6726SAlfredo Cardigliano return rte_eth_linkstatus_set(eth_dev, &link); 162598f6726SAlfredo Cardigliano } 163598f6726SAlfredo Cardigliano 16427b942c8SAlfredo Cardigliano /** 16527b942c8SAlfredo Cardigliano * Interrupt handler triggered by NIC for handling 16627b942c8SAlfredo Cardigliano * specific interrupt. 16727b942c8SAlfredo Cardigliano * 16827b942c8SAlfredo Cardigliano * @param param 16927b942c8SAlfredo Cardigliano * The address of parameter registered before. 17027b942c8SAlfredo Cardigliano * 17127b942c8SAlfredo Cardigliano * @return 17227b942c8SAlfredo Cardigliano * void 17327b942c8SAlfredo Cardigliano */ 17427b942c8SAlfredo Cardigliano static void 17527b942c8SAlfredo Cardigliano ionic_dev_interrupt_handler(void *param) 17627b942c8SAlfredo Cardigliano { 17727b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = (struct ionic_adapter *)param; 17827b942c8SAlfredo Cardigliano uint32_t i; 17927b942c8SAlfredo Cardigliano 18027b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "->"); 18127b942c8SAlfredo Cardigliano 18227b942c8SAlfredo Cardigliano for (i = 0; i < adapter->nlifs; i++) { 18327b942c8SAlfredo Cardigliano if (adapter->lifs[i]) 18427b942c8SAlfredo Cardigliano ionic_notifyq_handler(adapter->lifs[i], -1); 18527b942c8SAlfredo Cardigliano } 18627b942c8SAlfredo Cardigliano } 18727b942c8SAlfredo Cardigliano 188669c8de6SAlfredo Cardigliano static int 189598f6726SAlfredo Cardigliano ionic_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) 190598f6726SAlfredo Cardigliano { 191598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 192598f6726SAlfredo Cardigliano uint32_t max_frame_size; 193598f6726SAlfredo Cardigliano int err; 194598f6726SAlfredo Cardigliano 195598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 196598f6726SAlfredo Cardigliano 197598f6726SAlfredo Cardigliano /* 198598f6726SAlfredo Cardigliano * Note: mtu check against IONIC_MIN_MTU, IONIC_MAX_MTU 199598f6726SAlfredo Cardigliano * is done by the the API. 200598f6726SAlfredo Cardigliano */ 201598f6726SAlfredo Cardigliano 202598f6726SAlfredo Cardigliano /* 203598f6726SAlfredo Cardigliano * Max frame size is MTU + Ethernet header + VLAN + QinQ 204598f6726SAlfredo Cardigliano * (plus ETHER_CRC_LEN if the adapter is able to keep CRC) 205598f6726SAlfredo Cardigliano */ 206598f6726SAlfredo Cardigliano max_frame_size = mtu + RTE_ETHER_HDR_LEN + 4 + 4; 207598f6726SAlfredo Cardigliano 208598f6726SAlfredo Cardigliano if (eth_dev->data->dev_conf.rxmode.max_rx_pkt_len < max_frame_size) 209598f6726SAlfredo Cardigliano return -EINVAL; 210598f6726SAlfredo Cardigliano 211598f6726SAlfredo Cardigliano err = ionic_lif_change_mtu(lif, mtu); 212598f6726SAlfredo Cardigliano if (err) 213598f6726SAlfredo Cardigliano return err; 214598f6726SAlfredo Cardigliano 215598f6726SAlfredo Cardigliano return 0; 216598f6726SAlfredo Cardigliano } 217598f6726SAlfredo Cardigliano 218598f6726SAlfredo Cardigliano static int 219598f6726SAlfredo Cardigliano ionic_dev_info_get(struct rte_eth_dev *eth_dev, 220598f6726SAlfredo Cardigliano struct rte_eth_dev_info *dev_info) 221598f6726SAlfredo Cardigliano { 222598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 223598f6726SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 224598f6726SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 225598f6726SAlfredo Cardigliano 226598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 227598f6726SAlfredo Cardigliano 228598f6726SAlfredo Cardigliano dev_info->max_rx_queues = (uint16_t) 229598f6726SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 230598f6726SAlfredo Cardigliano dev_info->max_tx_queues = (uint16_t) 231598f6726SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 232598f6726SAlfredo Cardigliano /* Also add ETHER_CRC_LEN if the adapter is able to keep CRC */ 233598f6726SAlfredo Cardigliano dev_info->min_rx_bufsize = IONIC_MIN_MTU + RTE_ETHER_HDR_LEN; 234598f6726SAlfredo Cardigliano dev_info->max_rx_pktlen = IONIC_MAX_MTU + RTE_ETHER_HDR_LEN; 235598f6726SAlfredo Cardigliano dev_info->max_mac_addrs = adapter->max_mac_addrs; 236598f6726SAlfredo Cardigliano dev_info->min_mtu = IONIC_MIN_MTU; 237598f6726SAlfredo Cardigliano dev_info->max_mtu = IONIC_MAX_MTU; 238598f6726SAlfredo Cardigliano 239598f6726SAlfredo Cardigliano dev_info->speed_capa = 240598f6726SAlfredo Cardigliano ETH_LINK_SPEED_10G | 241598f6726SAlfredo Cardigliano ETH_LINK_SPEED_25G | 242598f6726SAlfredo Cardigliano ETH_LINK_SPEED_40G | 243598f6726SAlfredo Cardigliano ETH_LINK_SPEED_50G | 244598f6726SAlfredo Cardigliano ETH_LINK_SPEED_100G; 245598f6726SAlfredo Cardigliano 246598f6726SAlfredo Cardigliano return 0; 247598f6726SAlfredo Cardigliano } 248598f6726SAlfredo Cardigliano 249598f6726SAlfredo Cardigliano static int 250*ec15c66bSAlfredo Cardigliano ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev, 251*ec15c66bSAlfredo Cardigliano struct rte_eth_fc_conf *fc_conf) 252*ec15c66bSAlfredo Cardigliano { 253*ec15c66bSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 254*ec15c66bSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 255*ec15c66bSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 256*ec15c66bSAlfredo Cardigliano 257*ec15c66bSAlfredo Cardigliano if (idev->port_info) { 258*ec15c66bSAlfredo Cardigliano fc_conf->autoneg = idev->port_info->config.an_enable; 259*ec15c66bSAlfredo Cardigliano 260*ec15c66bSAlfredo Cardigliano if (idev->port_info->config.pause_type) 261*ec15c66bSAlfredo Cardigliano fc_conf->mode = RTE_FC_FULL; 262*ec15c66bSAlfredo Cardigliano else 263*ec15c66bSAlfredo Cardigliano fc_conf->mode = RTE_FC_NONE; 264*ec15c66bSAlfredo Cardigliano } 265*ec15c66bSAlfredo Cardigliano 266*ec15c66bSAlfredo Cardigliano return 0; 267*ec15c66bSAlfredo Cardigliano } 268*ec15c66bSAlfredo Cardigliano 269*ec15c66bSAlfredo Cardigliano static int 270*ec15c66bSAlfredo Cardigliano ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev, 271*ec15c66bSAlfredo Cardigliano struct rte_eth_fc_conf *fc_conf) 272*ec15c66bSAlfredo Cardigliano { 273*ec15c66bSAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 274*ec15c66bSAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 275*ec15c66bSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 276*ec15c66bSAlfredo Cardigliano uint8_t pause_type = IONIC_PORT_PAUSE_TYPE_NONE; 277*ec15c66bSAlfredo Cardigliano uint8_t an_enable; 278*ec15c66bSAlfredo Cardigliano 279*ec15c66bSAlfredo Cardigliano switch (fc_conf->mode) { 280*ec15c66bSAlfredo Cardigliano case RTE_FC_NONE: 281*ec15c66bSAlfredo Cardigliano pause_type = IONIC_PORT_PAUSE_TYPE_NONE; 282*ec15c66bSAlfredo Cardigliano break; 283*ec15c66bSAlfredo Cardigliano case RTE_FC_FULL: 284*ec15c66bSAlfredo Cardigliano pause_type = IONIC_PORT_PAUSE_TYPE_LINK; 285*ec15c66bSAlfredo Cardigliano break; 286*ec15c66bSAlfredo Cardigliano case RTE_FC_RX_PAUSE: 287*ec15c66bSAlfredo Cardigliano case RTE_FC_TX_PAUSE: 288*ec15c66bSAlfredo Cardigliano return -ENOTSUP; 289*ec15c66bSAlfredo Cardigliano } 290*ec15c66bSAlfredo Cardigliano 291*ec15c66bSAlfredo Cardigliano an_enable = fc_conf->autoneg; 292*ec15c66bSAlfredo Cardigliano 293*ec15c66bSAlfredo Cardigliano ionic_dev_cmd_port_pause(idev, pause_type); 294*ec15c66bSAlfredo Cardigliano ionic_dev_cmd_port_autoneg(idev, an_enable); 295*ec15c66bSAlfredo Cardigliano 296*ec15c66bSAlfredo Cardigliano return 0; 297*ec15c66bSAlfredo Cardigliano } 298*ec15c66bSAlfredo Cardigliano 299*ec15c66bSAlfredo Cardigliano static int 300598f6726SAlfredo Cardigliano ionic_dev_configure(struct rte_eth_dev *eth_dev) 301598f6726SAlfredo Cardigliano { 302598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 303598f6726SAlfredo Cardigliano int err; 304598f6726SAlfredo Cardigliano 305598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 306598f6726SAlfredo Cardigliano 307598f6726SAlfredo Cardigliano err = ionic_lif_configure(lif); 308598f6726SAlfredo Cardigliano if (err) { 309598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot configure LIF: %d", err); 310598f6726SAlfredo Cardigliano return err; 311598f6726SAlfredo Cardigliano } 312598f6726SAlfredo Cardigliano 313598f6726SAlfredo Cardigliano return 0; 314598f6726SAlfredo Cardigliano } 315598f6726SAlfredo Cardigliano 316598f6726SAlfredo Cardigliano static inline uint32_t 317598f6726SAlfredo Cardigliano ionic_parse_link_speeds(uint16_t link_speeds) 318598f6726SAlfredo Cardigliano { 319598f6726SAlfredo Cardigliano if (link_speeds & ETH_LINK_SPEED_100G) 320598f6726SAlfredo Cardigliano return 100000; 321598f6726SAlfredo Cardigliano else if (link_speeds & ETH_LINK_SPEED_50G) 322598f6726SAlfredo Cardigliano return 50000; 323598f6726SAlfredo Cardigliano else if (link_speeds & ETH_LINK_SPEED_40G) 324598f6726SAlfredo Cardigliano return 40000; 325598f6726SAlfredo Cardigliano else if (link_speeds & ETH_LINK_SPEED_25G) 326598f6726SAlfredo Cardigliano return 25000; 327598f6726SAlfredo Cardigliano else if (link_speeds & ETH_LINK_SPEED_10G) 328598f6726SAlfredo Cardigliano return 10000; 329598f6726SAlfredo Cardigliano else 330598f6726SAlfredo Cardigliano return 0; 331598f6726SAlfredo Cardigliano } 332598f6726SAlfredo Cardigliano 333598f6726SAlfredo Cardigliano /* 334598f6726SAlfredo Cardigliano * Configure device link speed and setup link. 335598f6726SAlfredo Cardigliano * It returns 0 on success. 336598f6726SAlfredo Cardigliano */ 337598f6726SAlfredo Cardigliano static int 338598f6726SAlfredo Cardigliano ionic_dev_start(struct rte_eth_dev *eth_dev) 339598f6726SAlfredo Cardigliano { 340598f6726SAlfredo Cardigliano struct rte_eth_conf *dev_conf = ð_dev->data->dev_conf; 341598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 342598f6726SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 343598f6726SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 344598f6726SAlfredo Cardigliano uint32_t allowed_speeds; 345598f6726SAlfredo Cardigliano int err; 346598f6726SAlfredo Cardigliano 347598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 348598f6726SAlfredo Cardigliano 349598f6726SAlfredo Cardigliano allowed_speeds = 350598f6726SAlfredo Cardigliano ETH_LINK_SPEED_FIXED | 351598f6726SAlfredo Cardigliano ETH_LINK_SPEED_10G | 352598f6726SAlfredo Cardigliano ETH_LINK_SPEED_25G | 353598f6726SAlfredo Cardigliano ETH_LINK_SPEED_40G | 354598f6726SAlfredo Cardigliano ETH_LINK_SPEED_50G | 355598f6726SAlfredo Cardigliano ETH_LINK_SPEED_100G; 356598f6726SAlfredo Cardigliano 357598f6726SAlfredo Cardigliano if (dev_conf->link_speeds & ~allowed_speeds) { 358598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Invalid link setting"); 359598f6726SAlfredo Cardigliano return -EINVAL; 360598f6726SAlfredo Cardigliano } 361598f6726SAlfredo Cardigliano 362598f6726SAlfredo Cardigliano err = ionic_lif_start(lif); 363598f6726SAlfredo Cardigliano if (err) { 364598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot start LIF: %d", err); 365598f6726SAlfredo Cardigliano return err; 366598f6726SAlfredo Cardigliano } 367598f6726SAlfredo Cardigliano 368598f6726SAlfredo Cardigliano if (eth_dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) { 369598f6726SAlfredo Cardigliano uint32_t speed = ionic_parse_link_speeds(dev_conf->link_speeds); 370598f6726SAlfredo Cardigliano 371598f6726SAlfredo Cardigliano if (speed) 372598f6726SAlfredo Cardigliano ionic_dev_cmd_port_speed(idev, speed); 373598f6726SAlfredo Cardigliano } 374598f6726SAlfredo Cardigliano 375598f6726SAlfredo Cardigliano ionic_dev_link_update(eth_dev, 0); 376598f6726SAlfredo Cardigliano 377598f6726SAlfredo Cardigliano return 0; 378598f6726SAlfredo Cardigliano } 379598f6726SAlfredo Cardigliano 380598f6726SAlfredo Cardigliano /* 381598f6726SAlfredo Cardigliano * Stop device: disable rx and tx functions to allow for reconfiguring. 382598f6726SAlfredo Cardigliano */ 383598f6726SAlfredo Cardigliano static void 384598f6726SAlfredo Cardigliano ionic_dev_stop(struct rte_eth_dev *eth_dev) 385598f6726SAlfredo Cardigliano { 386598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 387598f6726SAlfredo Cardigliano int err; 388598f6726SAlfredo Cardigliano 389598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 390598f6726SAlfredo Cardigliano 391598f6726SAlfredo Cardigliano err = ionic_lif_stop(lif); 392598f6726SAlfredo Cardigliano if (err) 393598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot stop LIF: %d", err); 394598f6726SAlfredo Cardigliano } 395598f6726SAlfredo Cardigliano 396598f6726SAlfredo Cardigliano /* 397598f6726SAlfredo Cardigliano * Reset and stop device. 398598f6726SAlfredo Cardigliano */ 399598f6726SAlfredo Cardigliano static void 400598f6726SAlfredo Cardigliano ionic_dev_close(struct rte_eth_dev *eth_dev) 401598f6726SAlfredo Cardigliano { 402598f6726SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 403598f6726SAlfredo Cardigliano int err; 404598f6726SAlfredo Cardigliano 405598f6726SAlfredo Cardigliano IONIC_PRINT_CALL(); 406598f6726SAlfredo Cardigliano 407598f6726SAlfredo Cardigliano err = ionic_lif_stop(lif); 408598f6726SAlfredo Cardigliano if (err) { 409598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot stop LIF: %d", err); 410598f6726SAlfredo Cardigliano return; 411598f6726SAlfredo Cardigliano } 412598f6726SAlfredo Cardigliano 413598f6726SAlfredo Cardigliano err = eth_ionic_dev_uninit(eth_dev); 414598f6726SAlfredo Cardigliano if (err) { 415598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot destroy LIF: %d", err); 416598f6726SAlfredo Cardigliano return; 417598f6726SAlfredo Cardigliano } 418598f6726SAlfredo Cardigliano } 419598f6726SAlfredo Cardigliano 420598f6726SAlfredo Cardigliano static int 421669c8de6SAlfredo Cardigliano eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params) 422669c8de6SAlfredo Cardigliano { 423669c8de6SAlfredo Cardigliano struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); 424669c8de6SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 425669c8de6SAlfredo Cardigliano struct ionic_adapter *adapter = (struct ionic_adapter *)init_params; 426669c8de6SAlfredo Cardigliano int err; 427669c8de6SAlfredo Cardigliano 428669c8de6SAlfredo Cardigliano IONIC_PRINT_CALL(); 429669c8de6SAlfredo Cardigliano 430669c8de6SAlfredo Cardigliano eth_dev->dev_ops = &ionic_eth_dev_ops; 431669c8de6SAlfredo Cardigliano 432669c8de6SAlfredo Cardigliano /* Multi-process not supported, primary does initialization anyway */ 433669c8de6SAlfredo Cardigliano if (rte_eal_process_type() != RTE_PROC_PRIMARY) 434669c8de6SAlfredo Cardigliano return 0; 435669c8de6SAlfredo Cardigliano 436669c8de6SAlfredo Cardigliano rte_eth_copy_pci_info(eth_dev, pci_dev); 437669c8de6SAlfredo Cardigliano 438669c8de6SAlfredo Cardigliano lif->index = adapter->nlifs; 439669c8de6SAlfredo Cardigliano lif->eth_dev = eth_dev; 440669c8de6SAlfredo Cardigliano lif->adapter = adapter; 441669c8de6SAlfredo Cardigliano adapter->lifs[adapter->nlifs] = lif; 442669c8de6SAlfredo Cardigliano 443598f6726SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Up to %u MAC addresses supported", 444598f6726SAlfredo Cardigliano adapter->max_mac_addrs); 445598f6726SAlfredo Cardigliano 446598f6726SAlfredo Cardigliano /* Allocate memory for storing MAC addresses */ 447598f6726SAlfredo Cardigliano eth_dev->data->mac_addrs = rte_zmalloc("ionic", 448598f6726SAlfredo Cardigliano RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs, 0); 449598f6726SAlfredo Cardigliano 450598f6726SAlfredo Cardigliano if (eth_dev->data->mac_addrs == NULL) { 451598f6726SAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to allocate %u bytes needed to " 452598f6726SAlfredo Cardigliano "store MAC addresses", 453598f6726SAlfredo Cardigliano RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs); 454598f6726SAlfredo Cardigliano err = -ENOMEM; 455598f6726SAlfredo Cardigliano goto err; 456598f6726SAlfredo Cardigliano } 457598f6726SAlfredo Cardigliano 458669c8de6SAlfredo Cardigliano err = ionic_lif_alloc(lif); 459669c8de6SAlfredo Cardigliano if (err) { 460669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate LIFs: %d, aborting", 461669c8de6SAlfredo Cardigliano err); 462669c8de6SAlfredo Cardigliano goto err; 463669c8de6SAlfredo Cardigliano } 464669c8de6SAlfredo Cardigliano 465669c8de6SAlfredo Cardigliano err = ionic_lif_init(lif); 466669c8de6SAlfredo Cardigliano if (err) { 467669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot init LIFs: %d, aborting", err); 468669c8de6SAlfredo Cardigliano goto err_free_lif; 469669c8de6SAlfredo Cardigliano } 470669c8de6SAlfredo Cardigliano 471598f6726SAlfredo Cardigliano /* Copy the MAC address */ 472598f6726SAlfredo Cardigliano rte_ether_addr_copy((struct rte_ether_addr *)lif->mac_addr, 473598f6726SAlfredo Cardigliano ð_dev->data->mac_addrs[0]); 474598f6726SAlfredo Cardigliano 475669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Port %u initialized", eth_dev->data->port_id); 476669c8de6SAlfredo Cardigliano 477669c8de6SAlfredo Cardigliano return 0; 478669c8de6SAlfredo Cardigliano 479669c8de6SAlfredo Cardigliano err_free_lif: 480669c8de6SAlfredo Cardigliano ionic_lif_free(lif); 481669c8de6SAlfredo Cardigliano err: 482669c8de6SAlfredo Cardigliano return err; 483669c8de6SAlfredo Cardigliano } 484669c8de6SAlfredo Cardigliano 485669c8de6SAlfredo Cardigliano static int 486669c8de6SAlfredo Cardigliano eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev) 487669c8de6SAlfredo Cardigliano { 488669c8de6SAlfredo Cardigliano struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 489669c8de6SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 490669c8de6SAlfredo Cardigliano 491669c8de6SAlfredo Cardigliano IONIC_PRINT_CALL(); 492669c8de6SAlfredo Cardigliano 493669c8de6SAlfredo Cardigliano if (rte_eal_process_type() != RTE_PROC_PRIMARY) 494669c8de6SAlfredo Cardigliano return 0; 495669c8de6SAlfredo Cardigliano 496669c8de6SAlfredo Cardigliano adapter->lifs[lif->index] = NULL; 497669c8de6SAlfredo Cardigliano 498669c8de6SAlfredo Cardigliano ionic_lif_deinit(lif); 499669c8de6SAlfredo Cardigliano ionic_lif_free(lif); 500669c8de6SAlfredo Cardigliano 501669c8de6SAlfredo Cardigliano eth_dev->dev_ops = NULL; 502669c8de6SAlfredo Cardigliano 503669c8de6SAlfredo Cardigliano return 0; 504669c8de6SAlfredo Cardigliano } 505669c8de6SAlfredo Cardigliano 5065ef51809SAlfredo Cardigliano static int 50727b942c8SAlfredo Cardigliano ionic_configure_intr(struct ionic_adapter *adapter) 50827b942c8SAlfredo Cardigliano { 50927b942c8SAlfredo Cardigliano struct rte_pci_device *pci_dev = adapter->pci_dev; 51027b942c8SAlfredo Cardigliano struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; 51127b942c8SAlfredo Cardigliano int err; 51227b942c8SAlfredo Cardigliano 51327b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Configuring %u intrs", adapter->nintrs); 51427b942c8SAlfredo Cardigliano 51527b942c8SAlfredo Cardigliano if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) { 51627b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Fail to create eventfd"); 51727b942c8SAlfredo Cardigliano return -1; 51827b942c8SAlfredo Cardigliano } 51927b942c8SAlfredo Cardigliano 52027b942c8SAlfredo Cardigliano if (rte_intr_dp_is_en(intr_handle)) 52127b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 52227b942c8SAlfredo Cardigliano "Packet I/O interrupt on datapath is enabled"); 52327b942c8SAlfredo Cardigliano 52427b942c8SAlfredo Cardigliano if (!intr_handle->intr_vec) { 52527b942c8SAlfredo Cardigliano intr_handle->intr_vec = rte_zmalloc("intr_vec", 52627b942c8SAlfredo Cardigliano adapter->nintrs * sizeof(int), 0); 52727b942c8SAlfredo Cardigliano 52827b942c8SAlfredo Cardigliano if (!intr_handle->intr_vec) { 52927b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to allocate %u vectors", 53027b942c8SAlfredo Cardigliano adapter->nintrs); 53127b942c8SAlfredo Cardigliano return -ENOMEM; 53227b942c8SAlfredo Cardigliano } 53327b942c8SAlfredo Cardigliano } 53427b942c8SAlfredo Cardigliano 53527b942c8SAlfredo Cardigliano err = rte_intr_callback_register(intr_handle, 53627b942c8SAlfredo Cardigliano ionic_dev_interrupt_handler, 53727b942c8SAlfredo Cardigliano adapter); 53827b942c8SAlfredo Cardigliano 53927b942c8SAlfredo Cardigliano if (err) { 54027b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, 54127b942c8SAlfredo Cardigliano "Failure registering interrupts handler (%d)", 54227b942c8SAlfredo Cardigliano err); 54327b942c8SAlfredo Cardigliano return err; 54427b942c8SAlfredo Cardigliano } 54527b942c8SAlfredo Cardigliano 54627b942c8SAlfredo Cardigliano /* enable intr mapping */ 54727b942c8SAlfredo Cardigliano err = rte_intr_enable(intr_handle); 54827b942c8SAlfredo Cardigliano 54927b942c8SAlfredo Cardigliano if (err) { 55027b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err); 55127b942c8SAlfredo Cardigliano return err; 55227b942c8SAlfredo Cardigliano } 55327b942c8SAlfredo Cardigliano 55427b942c8SAlfredo Cardigliano return 0; 55527b942c8SAlfredo Cardigliano } 55627b942c8SAlfredo Cardigliano 55727b942c8SAlfredo Cardigliano static void 55827b942c8SAlfredo Cardigliano ionic_unconfigure_intr(struct ionic_adapter *adapter) 55927b942c8SAlfredo Cardigliano { 56027b942c8SAlfredo Cardigliano struct rte_pci_device *pci_dev = adapter->pci_dev; 56127b942c8SAlfredo Cardigliano struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; 56227b942c8SAlfredo Cardigliano 56327b942c8SAlfredo Cardigliano rte_intr_disable(intr_handle); 56427b942c8SAlfredo Cardigliano 56527b942c8SAlfredo Cardigliano rte_intr_callback_unregister(intr_handle, 56627b942c8SAlfredo Cardigliano ionic_dev_interrupt_handler, 56727b942c8SAlfredo Cardigliano adapter); 56827b942c8SAlfredo Cardigliano } 56927b942c8SAlfredo Cardigliano 57027b942c8SAlfredo Cardigliano static int 5715ef51809SAlfredo Cardigliano eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 5725ef51809SAlfredo Cardigliano struct rte_pci_device *pci_dev) 5735ef51809SAlfredo Cardigliano { 574669c8de6SAlfredo Cardigliano char name[RTE_ETH_NAME_MAX_LEN]; 5755ef51809SAlfredo Cardigliano struct rte_mem_resource *resource; 5765ef51809SAlfredo Cardigliano struct ionic_adapter *adapter; 5775ef51809SAlfredo Cardigliano struct ionic_hw *hw; 5785ef51809SAlfredo Cardigliano unsigned long i; 5795ef51809SAlfredo Cardigliano int err; 5805ef51809SAlfredo Cardigliano 5815ef51809SAlfredo Cardigliano /* Check structs (trigger error at compilation time) */ 5825ef51809SAlfredo Cardigliano ionic_struct_size_checks(); 5835ef51809SAlfredo Cardigliano 5845ef51809SAlfredo Cardigliano /* Multi-process not supported */ 5855ef51809SAlfredo Cardigliano if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 5865ef51809SAlfredo Cardigliano err = -EPERM; 5875ef51809SAlfredo Cardigliano goto err; 5885ef51809SAlfredo Cardigliano } 5895ef51809SAlfredo Cardigliano 5905ef51809SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Initializing device %s", 5915ef51809SAlfredo Cardigliano pci_dev->device.name); 5925ef51809SAlfredo Cardigliano 5935ef51809SAlfredo Cardigliano adapter = rte_zmalloc("ionic", sizeof(*adapter), 0); 5945ef51809SAlfredo Cardigliano if (!adapter) { 5955ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "OOM"); 5965ef51809SAlfredo Cardigliano err = -ENOMEM; 5975ef51809SAlfredo Cardigliano goto err; 5985ef51809SAlfredo Cardigliano } 5995ef51809SAlfredo Cardigliano 6005ef51809SAlfredo Cardigliano adapter->pci_dev = pci_dev; 6015ef51809SAlfredo Cardigliano hw = &adapter->hw; 6025ef51809SAlfredo Cardigliano 6035ef51809SAlfredo Cardigliano hw->device_id = pci_dev->id.device_id; 6045ef51809SAlfredo Cardigliano hw->vendor_id = pci_dev->id.vendor_id; 6055ef51809SAlfredo Cardigliano 6065ef51809SAlfredo Cardigliano err = ionic_init_mac(hw); 6075ef51809SAlfredo Cardigliano if (err != 0) { 6085ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Mac init failed: %d", err); 6095ef51809SAlfredo Cardigliano err = -EIO; 6105ef51809SAlfredo Cardigliano goto err_free_adapter; 6115ef51809SAlfredo Cardigliano } 6125ef51809SAlfredo Cardigliano 6135ef51809SAlfredo Cardigliano adapter->is_mgmt_nic = (pci_dev->id.device_id == IONIC_DEV_ID_ETH_MGMT); 6145ef51809SAlfredo Cardigliano 6155ef51809SAlfredo Cardigliano adapter->num_bars = 0; 6165ef51809SAlfredo Cardigliano for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) { 6175ef51809SAlfredo Cardigliano resource = &pci_dev->mem_resource[i]; 6185ef51809SAlfredo Cardigliano if (resource->phys_addr == 0 || resource->len == 0) 6195ef51809SAlfredo Cardigliano continue; 6205ef51809SAlfredo Cardigliano adapter->bars[adapter->num_bars].vaddr = resource->addr; 6215ef51809SAlfredo Cardigliano adapter->bars[adapter->num_bars].bus_addr = resource->phys_addr; 6225ef51809SAlfredo Cardigliano adapter->bars[adapter->num_bars].len = resource->len; 6235ef51809SAlfredo Cardigliano adapter->num_bars++; 6245ef51809SAlfredo Cardigliano } 6255ef51809SAlfredo Cardigliano 6265ef51809SAlfredo Cardigliano /* Discover ionic dev resources */ 6275ef51809SAlfredo Cardigliano 6285ef51809SAlfredo Cardigliano err = ionic_setup(adapter); 6295ef51809SAlfredo Cardigliano if (err) { 6305ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot setup device: %d, aborting", err); 6315ef51809SAlfredo Cardigliano goto err_free_adapter; 6325ef51809SAlfredo Cardigliano } 6335ef51809SAlfredo Cardigliano 6345ef51809SAlfredo Cardigliano err = ionic_identify(adapter); 6355ef51809SAlfredo Cardigliano if (err) { 6365ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot identify device: %d, aborting", 6375ef51809SAlfredo Cardigliano err); 6385ef51809SAlfredo Cardigliano goto err_free_adapter; 6395ef51809SAlfredo Cardigliano } 6405ef51809SAlfredo Cardigliano 6415ef51809SAlfredo Cardigliano err = ionic_init(adapter); 6425ef51809SAlfredo Cardigliano if (err) { 6435ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot init device: %d, aborting", err); 6445ef51809SAlfredo Cardigliano goto err_free_adapter; 6455ef51809SAlfredo Cardigliano } 6465ef51809SAlfredo Cardigliano 64723bf4ddbSAlfredo Cardigliano /* Configure the ports */ 64823bf4ddbSAlfredo Cardigliano err = ionic_port_identify(adapter); 64923bf4ddbSAlfredo Cardigliano if (err) { 65023bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot identify port: %d, aborting", 65123bf4ddbSAlfredo Cardigliano err); 65223bf4ddbSAlfredo Cardigliano goto err_free_adapter; 65323bf4ddbSAlfredo Cardigliano } 65423bf4ddbSAlfredo Cardigliano 65523bf4ddbSAlfredo Cardigliano err = ionic_port_init(adapter); 65623bf4ddbSAlfredo Cardigliano if (err) { 65723bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot init port: %d, aborting", err); 65823bf4ddbSAlfredo Cardigliano goto err_free_adapter; 65923bf4ddbSAlfredo Cardigliano } 66023bf4ddbSAlfredo Cardigliano 661669c8de6SAlfredo Cardigliano /* Configure LIFs */ 662669c8de6SAlfredo Cardigliano err = ionic_lif_identify(adapter); 663669c8de6SAlfredo Cardigliano if (err) { 664669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot identify lif: %d, aborting", err); 665669c8de6SAlfredo Cardigliano goto err_free_adapter; 666669c8de6SAlfredo Cardigliano } 667669c8de6SAlfredo Cardigliano 668669c8de6SAlfredo Cardigliano /* Allocate and init LIFs */ 669669c8de6SAlfredo Cardigliano err = ionic_lifs_size(adapter); 670669c8de6SAlfredo Cardigliano if (err) { 671669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot size LIFs: %d, aborting", err); 672669c8de6SAlfredo Cardigliano goto err_free_adapter; 673669c8de6SAlfredo Cardigliano } 674669c8de6SAlfredo Cardigliano 675598f6726SAlfredo Cardigliano adapter->max_mac_addrs = adapter->ident.lif.eth.max_ucast_filters; 676598f6726SAlfredo Cardigliano 677669c8de6SAlfredo Cardigliano adapter->nlifs = 0; 678669c8de6SAlfredo Cardigliano for (i = 0; i < adapter->ident.dev.nlifs; i++) { 679669c8de6SAlfredo Cardigliano snprintf(name, sizeof(name), "net_%s_lif_%lu", 680669c8de6SAlfredo Cardigliano pci_dev->device.name, i); 681669c8de6SAlfredo Cardigliano 682669c8de6SAlfredo Cardigliano err = rte_eth_dev_create(&pci_dev->device, name, 683669c8de6SAlfredo Cardigliano sizeof(struct ionic_lif), 684669c8de6SAlfredo Cardigliano NULL, NULL, 685669c8de6SAlfredo Cardigliano eth_ionic_dev_init, adapter); 686669c8de6SAlfredo Cardigliano if (err) { 687669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot create eth device for " 688669c8de6SAlfredo Cardigliano "ionic lif %s", name); 689669c8de6SAlfredo Cardigliano break; 690669c8de6SAlfredo Cardigliano } 691669c8de6SAlfredo Cardigliano 692669c8de6SAlfredo Cardigliano adapter->nlifs++; 693669c8de6SAlfredo Cardigliano } 694669c8de6SAlfredo Cardigliano 69527b942c8SAlfredo Cardigliano err = ionic_configure_intr(adapter); 69627b942c8SAlfredo Cardigliano 69727b942c8SAlfredo Cardigliano if (err) { 69827b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to configure interrupts"); 69927b942c8SAlfredo Cardigliano goto err_free_adapter; 70027b942c8SAlfredo Cardigliano } 70127b942c8SAlfredo Cardigliano 7025ef51809SAlfredo Cardigliano return 0; 7035ef51809SAlfredo Cardigliano 7045ef51809SAlfredo Cardigliano err_free_adapter: 7055ef51809SAlfredo Cardigliano rte_free(adapter); 7065ef51809SAlfredo Cardigliano err: 7075ef51809SAlfredo Cardigliano return err; 7085ef51809SAlfredo Cardigliano } 7095ef51809SAlfredo Cardigliano 7105ef51809SAlfredo Cardigliano static int 7115ef51809SAlfredo Cardigliano eth_ionic_pci_remove(struct rte_pci_device *pci_dev __rte_unused) 7125ef51809SAlfredo Cardigliano { 713669c8de6SAlfredo Cardigliano char name[RTE_ETH_NAME_MAX_LEN]; 714669c8de6SAlfredo Cardigliano struct ionic_adapter *adapter = NULL; 715669c8de6SAlfredo Cardigliano struct rte_eth_dev *eth_dev; 716669c8de6SAlfredo Cardigliano struct ionic_lif *lif; 717669c8de6SAlfredo Cardigliano uint32_t i; 718669c8de6SAlfredo Cardigliano 719669c8de6SAlfredo Cardigliano /* Adapter lookup is using (the first) eth_dev name */ 720669c8de6SAlfredo Cardigliano snprintf(name, sizeof(name), "net_%s_lif_0", 721669c8de6SAlfredo Cardigliano pci_dev->device.name); 722669c8de6SAlfredo Cardigliano 723669c8de6SAlfredo Cardigliano eth_dev = rte_eth_dev_allocated(name); 724669c8de6SAlfredo Cardigliano if (eth_dev) { 725669c8de6SAlfredo Cardigliano lif = IONIC_ETH_DEV_TO_LIF(eth_dev); 726669c8de6SAlfredo Cardigliano adapter = lif->adapter; 727669c8de6SAlfredo Cardigliano } 728669c8de6SAlfredo Cardigliano 729669c8de6SAlfredo Cardigliano if (adapter) { 73027b942c8SAlfredo Cardigliano ionic_unconfigure_intr(adapter); 73127b942c8SAlfredo Cardigliano 732669c8de6SAlfredo Cardigliano for (i = 0; i < adapter->nlifs; i++) { 733669c8de6SAlfredo Cardigliano lif = adapter->lifs[i]; 734669c8de6SAlfredo Cardigliano rte_eth_dev_destroy(lif->eth_dev, eth_ionic_dev_uninit); 735669c8de6SAlfredo Cardigliano } 736669c8de6SAlfredo Cardigliano 737669c8de6SAlfredo Cardigliano rte_free(adapter); 738669c8de6SAlfredo Cardigliano } 739669c8de6SAlfredo Cardigliano 7405ef51809SAlfredo Cardigliano return 0; 7415ef51809SAlfredo Cardigliano } 7425ef51809SAlfredo Cardigliano 7435ef51809SAlfredo Cardigliano static struct rte_pci_driver rte_ionic_pmd = { 7445ef51809SAlfredo Cardigliano .id_table = pci_id_ionic_map, 7455ef51809SAlfredo Cardigliano .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, 7465ef51809SAlfredo Cardigliano .probe = eth_ionic_pci_probe, 7475ef51809SAlfredo Cardigliano .remove = eth_ionic_pci_remove, 7485ef51809SAlfredo Cardigliano }; 7495ef51809SAlfredo Cardigliano 7505ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI(net_ionic, rte_ionic_pmd); 7515ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_PCI_TABLE(net_ionic, pci_id_ionic_map); 7525ef51809SAlfredo Cardigliano RTE_PMD_REGISTER_KMOD_DEP(net_ionic, "* igb_uio | uio_pci_generic | vfio-pci"); 7535ef51809SAlfredo Cardigliano 7547c125393SAlfredo Cardigliano RTE_INIT(ionic_init_log) 7557c125393SAlfredo Cardigliano { 7567c125393SAlfredo Cardigliano ionic_logtype = rte_log_register("pmd.net.ionic"); 7577c125393SAlfredo Cardigliano if (ionic_logtype >= 0) 7587c125393SAlfredo Cardigliano rte_log_set_level(ionic_logtype, RTE_LOG_NOTICE); 7597c125393SAlfredo Cardigliano } 760