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