1*4ccc8d77SZyta Szpak /* SPDX-License-Identifier: BSD-3-Clause 2*4ccc8d77SZyta Szpak * Copyright(c) 2018 Marvell International Ltd. 3*4ccc8d77SZyta Szpak * Copyright(c) 2018 Semihalf. 4*4ccc8d77SZyta Szpak * All rights reserved. 5*4ccc8d77SZyta Szpak */ 6*4ccc8d77SZyta Szpak 7*4ccc8d77SZyta Szpak #include <rte_ethdev_driver.h> 8*4ccc8d77SZyta Szpak #include <rte_kvargs.h> 9*4ccc8d77SZyta Szpak #include <rte_log.h> 10*4ccc8d77SZyta Szpak #include <rte_malloc.h> 11*4ccc8d77SZyta Szpak #include <rte_bus_vdev.h> 12*4ccc8d77SZyta Szpak 13*4ccc8d77SZyta Szpak #include <stdio.h> 14*4ccc8d77SZyta Szpak #include <fcntl.h> 15*4ccc8d77SZyta Szpak #include <linux/ethtool.h> 16*4ccc8d77SZyta Szpak #include <linux/sockios.h> 17*4ccc8d77SZyta Szpak #include <net/if.h> 18*4ccc8d77SZyta Szpak #include <net/if_arp.h> 19*4ccc8d77SZyta Szpak #include <sys/ioctl.h> 20*4ccc8d77SZyta Szpak #include <sys/socket.h> 21*4ccc8d77SZyta Szpak #include <sys/stat.h> 22*4ccc8d77SZyta Szpak #include <sys/types.h> 23*4ccc8d77SZyta Szpak 24*4ccc8d77SZyta Szpak #include <rte_mvep_common.h> 25*4ccc8d77SZyta Szpak 26*4ccc8d77SZyta Szpak #include "mvneta_ethdev.h" 27*4ccc8d77SZyta Szpak 28*4ccc8d77SZyta Szpak 29*4ccc8d77SZyta Szpak #define MVNETA_IFACE_NAME_ARG "iface" 30*4ccc8d77SZyta Szpak 31*4ccc8d77SZyta Szpak #define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \ 32*4ccc8d77SZyta Szpak DEV_RX_OFFLOAD_CHECKSUM) 33*4ccc8d77SZyta Szpak 34*4ccc8d77SZyta Szpak /** Port Tx offloads capabilities */ 35*4ccc8d77SZyta Szpak #define MVNETA_TX_OFFLOADS (DEV_TX_OFFLOAD_IPV4_CKSUM | \ 36*4ccc8d77SZyta Szpak DEV_TX_OFFLOAD_UDP_CKSUM | \ 37*4ccc8d77SZyta Szpak DEV_TX_OFFLOAD_TCP_CKSUM | \ 38*4ccc8d77SZyta Szpak DEV_TX_OFFLOAD_MULTI_SEGS) 39*4ccc8d77SZyta Szpak 40*4ccc8d77SZyta Szpak #define MVNETA_PKT_SIZE_MAX (16382 - MV_MH_SIZE) /* 9700B */ 41*4ccc8d77SZyta Szpak #define MVNETA_DEFAULT_MTU 1500 42*4ccc8d77SZyta Szpak 43*4ccc8d77SZyta Szpak #define MVNETA_MAC_ADDRS_MAX 256 /*16 UC, 256 IP, 256 MC/BC */ 44*4ccc8d77SZyta Szpak /** Maximum length of a match string */ 45*4ccc8d77SZyta Szpak #define MVNETA_MATCH_LEN 16 46*4ccc8d77SZyta Szpak 47*4ccc8d77SZyta Szpak int mvneta_logtype; 48*4ccc8d77SZyta Szpak 49*4ccc8d77SZyta Szpak static const char * const valid_args[] = { 50*4ccc8d77SZyta Szpak MVNETA_IFACE_NAME_ARG, 51*4ccc8d77SZyta Szpak NULL 52*4ccc8d77SZyta Szpak }; 53*4ccc8d77SZyta Szpak 54*4ccc8d77SZyta Szpak struct mvneta_ifnames { 55*4ccc8d77SZyta Szpak const char *names[NETA_NUM_ETH_PPIO]; 56*4ccc8d77SZyta Szpak int idx; 57*4ccc8d77SZyta Szpak }; 58*4ccc8d77SZyta Szpak 59*4ccc8d77SZyta Szpak static int mvneta_dev_num; 60*4ccc8d77SZyta Szpak 61*4ccc8d77SZyta Szpak /** 62*4ccc8d77SZyta Szpak * Deinitialize packet processor. 63*4ccc8d77SZyta Szpak */ 64*4ccc8d77SZyta Szpak static void 65*4ccc8d77SZyta Szpak mvneta_neta_deinit(void) 66*4ccc8d77SZyta Szpak { 67*4ccc8d77SZyta Szpak neta_deinit(); 68*4ccc8d77SZyta Szpak } 69*4ccc8d77SZyta Szpak 70*4ccc8d77SZyta Szpak /** 71*4ccc8d77SZyta Szpak * Initialize packet processor. 72*4ccc8d77SZyta Szpak * 73*4ccc8d77SZyta Szpak * @return 74*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 75*4ccc8d77SZyta Szpak */ 76*4ccc8d77SZyta Szpak static int 77*4ccc8d77SZyta Szpak mvneta_neta_init(void) 78*4ccc8d77SZyta Szpak { 79*4ccc8d77SZyta Szpak return neta_init(); 80*4ccc8d77SZyta Szpak } 81*4ccc8d77SZyta Szpak 82*4ccc8d77SZyta Szpak /** 83*4ccc8d77SZyta Szpak * Callback used by rte_kvargs_process() during argument parsing. 84*4ccc8d77SZyta Szpak * 85*4ccc8d77SZyta Szpak * @param key 86*4ccc8d77SZyta Szpak * Pointer to the parsed key (unused). 87*4ccc8d77SZyta Szpak * @param value 88*4ccc8d77SZyta Szpak * Pointer to the parsed value. 89*4ccc8d77SZyta Szpak * @param extra_args 90*4ccc8d77SZyta Szpak * Pointer to the extra arguments which contains address of the 91*4ccc8d77SZyta Szpak * table of pointers to parsed interface names. 92*4ccc8d77SZyta Szpak * 93*4ccc8d77SZyta Szpak * @return 94*4ccc8d77SZyta Szpak * Always 0. 95*4ccc8d77SZyta Szpak */ 96*4ccc8d77SZyta Szpak static int 97*4ccc8d77SZyta Szpak mvneta_ifnames_get(const char *key __rte_unused, const char *value, 98*4ccc8d77SZyta Szpak void *extra_args) 99*4ccc8d77SZyta Szpak { 100*4ccc8d77SZyta Szpak struct mvneta_ifnames *ifnames = extra_args; 101*4ccc8d77SZyta Szpak 102*4ccc8d77SZyta Szpak ifnames->names[ifnames->idx++] = value; 103*4ccc8d77SZyta Szpak 104*4ccc8d77SZyta Szpak return 0; 105*4ccc8d77SZyta Szpak } 106*4ccc8d77SZyta Szpak 107*4ccc8d77SZyta Szpak /** 108*4ccc8d77SZyta Szpak * Ethernet device configuration. 109*4ccc8d77SZyta Szpak * 110*4ccc8d77SZyta Szpak * Prepare the driver for a given number of TX and RX queues and 111*4ccc8d77SZyta Szpak * configure RSS if supported. 112*4ccc8d77SZyta Szpak * 113*4ccc8d77SZyta Szpak * @param dev 114*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 115*4ccc8d77SZyta Szpak * 116*4ccc8d77SZyta Szpak * @return 117*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 118*4ccc8d77SZyta Szpak */ 119*4ccc8d77SZyta Szpak static int 120*4ccc8d77SZyta Szpak mvneta_dev_configure(struct rte_eth_dev *dev) 121*4ccc8d77SZyta Szpak { 122*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 123*4ccc8d77SZyta Szpak struct neta_ppio_params *ppio_params; 124*4ccc8d77SZyta Szpak 125*4ccc8d77SZyta Szpak if (dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_NONE) { 126*4ccc8d77SZyta Szpak MVNETA_LOG(INFO, "Unsupported RSS and rx multi queue mode %d", 127*4ccc8d77SZyta Szpak dev->data->dev_conf.rxmode.mq_mode); 128*4ccc8d77SZyta Szpak if (dev->data->nb_rx_queues > 1) 129*4ccc8d77SZyta Szpak return -EINVAL; 130*4ccc8d77SZyta Szpak } 131*4ccc8d77SZyta Szpak 132*4ccc8d77SZyta Szpak if (dev->data->dev_conf.rxmode.split_hdr_size) { 133*4ccc8d77SZyta Szpak MVNETA_LOG(INFO, "Split headers not supported"); 134*4ccc8d77SZyta Szpak return -EINVAL; 135*4ccc8d77SZyta Szpak } 136*4ccc8d77SZyta Szpak 137*4ccc8d77SZyta Szpak if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) 138*4ccc8d77SZyta Szpak dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len - 139*4ccc8d77SZyta Szpak MRVL_NETA_ETH_HDRS_LEN; 140*4ccc8d77SZyta Szpak 141*4ccc8d77SZyta Szpak if (dev->data->dev_conf.txmode.offloads & DEV_TX_OFFLOAD_MULTI_SEGS) 142*4ccc8d77SZyta Szpak priv->multiseg = 1; 143*4ccc8d77SZyta Szpak 144*4ccc8d77SZyta Szpak ppio_params = &priv->ppio_params; 145*4ccc8d77SZyta Szpak ppio_params->outqs_params.num_outqs = dev->data->nb_tx_queues; 146*4ccc8d77SZyta Szpak /* Default: 1 TC, no QoS supported. */ 147*4ccc8d77SZyta Szpak ppio_params->inqs_params.num_tcs = 1; 148*4ccc8d77SZyta Szpak ppio_params->inqs_params.tcs_params[0].pkt_offset = MRVL_NETA_PKT_OFFS; 149*4ccc8d77SZyta Szpak priv->ppio_id = dev->data->port_id; 150*4ccc8d77SZyta Szpak 151*4ccc8d77SZyta Szpak return 0; 152*4ccc8d77SZyta Szpak } 153*4ccc8d77SZyta Szpak 154*4ccc8d77SZyta Szpak /** 155*4ccc8d77SZyta Szpak * DPDK callback to get information about the device. 156*4ccc8d77SZyta Szpak * 157*4ccc8d77SZyta Szpak * @param dev 158*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure (unused). 159*4ccc8d77SZyta Szpak * @param info 160*4ccc8d77SZyta Szpak * Info structure output buffer. 161*4ccc8d77SZyta Szpak */ 162*4ccc8d77SZyta Szpak static void 163*4ccc8d77SZyta Szpak mvneta_dev_infos_get(struct rte_eth_dev *dev __rte_unused, 164*4ccc8d77SZyta Szpak struct rte_eth_dev_info *info) 165*4ccc8d77SZyta Szpak { 166*4ccc8d77SZyta Szpak info->speed_capa = ETH_LINK_SPEED_10M | 167*4ccc8d77SZyta Szpak ETH_LINK_SPEED_100M | 168*4ccc8d77SZyta Szpak ETH_LINK_SPEED_1G | 169*4ccc8d77SZyta Szpak ETH_LINK_SPEED_2_5G; 170*4ccc8d77SZyta Szpak 171*4ccc8d77SZyta Szpak info->max_rx_queues = MRVL_NETA_RXQ_MAX; 172*4ccc8d77SZyta Szpak info->max_tx_queues = MRVL_NETA_TXQ_MAX; 173*4ccc8d77SZyta Szpak info->max_mac_addrs = MVNETA_MAC_ADDRS_MAX; 174*4ccc8d77SZyta Szpak 175*4ccc8d77SZyta Szpak info->rx_desc_lim.nb_max = MRVL_NETA_RXD_MAX; 176*4ccc8d77SZyta Szpak info->rx_desc_lim.nb_min = MRVL_NETA_RXD_MIN; 177*4ccc8d77SZyta Szpak info->rx_desc_lim.nb_align = MRVL_NETA_RXD_ALIGN; 178*4ccc8d77SZyta Szpak 179*4ccc8d77SZyta Szpak info->tx_desc_lim.nb_max = MRVL_NETA_TXD_MAX; 180*4ccc8d77SZyta Szpak info->tx_desc_lim.nb_min = MRVL_NETA_TXD_MIN; 181*4ccc8d77SZyta Szpak info->tx_desc_lim.nb_align = MRVL_NETA_TXD_ALIGN; 182*4ccc8d77SZyta Szpak 183*4ccc8d77SZyta Szpak info->rx_offload_capa = MVNETA_RX_OFFLOADS; 184*4ccc8d77SZyta Szpak info->rx_queue_offload_capa = MVNETA_RX_OFFLOADS; 185*4ccc8d77SZyta Szpak 186*4ccc8d77SZyta Szpak info->tx_offload_capa = MVNETA_TX_OFFLOADS; 187*4ccc8d77SZyta Szpak info->tx_queue_offload_capa = MVNETA_TX_OFFLOADS; 188*4ccc8d77SZyta Szpak 189*4ccc8d77SZyta Szpak /* By default packets are dropped if no descriptors are available */ 190*4ccc8d77SZyta Szpak info->default_rxconf.rx_drop_en = 1; 191*4ccc8d77SZyta Szpak /* Deferred tx queue start is not supported */ 192*4ccc8d77SZyta Szpak info->default_txconf.tx_deferred_start = 0; 193*4ccc8d77SZyta Szpak info->default_txconf.offloads = 0; 194*4ccc8d77SZyta Szpak 195*4ccc8d77SZyta Szpak info->max_rx_pktlen = MVNETA_PKT_SIZE_MAX; 196*4ccc8d77SZyta Szpak } 197*4ccc8d77SZyta Szpak 198*4ccc8d77SZyta Szpak /** 199*4ccc8d77SZyta Szpak * Return supported packet types. 200*4ccc8d77SZyta Szpak * 201*4ccc8d77SZyta Szpak * @param dev 202*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure (unused). 203*4ccc8d77SZyta Szpak * 204*4ccc8d77SZyta Szpak * @return 205*4ccc8d77SZyta Szpak * Const pointer to the table with supported packet types. 206*4ccc8d77SZyta Szpak */ 207*4ccc8d77SZyta Szpak static const uint32_t * 208*4ccc8d77SZyta Szpak mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused) 209*4ccc8d77SZyta Szpak { 210*4ccc8d77SZyta Szpak static const uint32_t ptypes[] = { 211*4ccc8d77SZyta Szpak RTE_PTYPE_L2_ETHER, 212*4ccc8d77SZyta Szpak RTE_PTYPE_L2_ETHER_VLAN, 213*4ccc8d77SZyta Szpak RTE_PTYPE_L3_IPV4, 214*4ccc8d77SZyta Szpak RTE_PTYPE_L3_IPV6, 215*4ccc8d77SZyta Szpak RTE_PTYPE_L4_TCP, 216*4ccc8d77SZyta Szpak RTE_PTYPE_L4_UDP 217*4ccc8d77SZyta Szpak }; 218*4ccc8d77SZyta Szpak 219*4ccc8d77SZyta Szpak return ptypes; 220*4ccc8d77SZyta Szpak } 221*4ccc8d77SZyta Szpak 222*4ccc8d77SZyta Szpak /** 223*4ccc8d77SZyta Szpak * DPDK callback to bring the link up. 224*4ccc8d77SZyta Szpak * 225*4ccc8d77SZyta Szpak * @param dev 226*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 227*4ccc8d77SZyta Szpak * 228*4ccc8d77SZyta Szpak * @return 229*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 230*4ccc8d77SZyta Szpak */ 231*4ccc8d77SZyta Szpak static int 232*4ccc8d77SZyta Szpak mvneta_dev_set_link_up(struct rte_eth_dev *dev) 233*4ccc8d77SZyta Szpak { 234*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 235*4ccc8d77SZyta Szpak 236*4ccc8d77SZyta Szpak if (!priv->ppio) 237*4ccc8d77SZyta Szpak return 0; 238*4ccc8d77SZyta Szpak 239*4ccc8d77SZyta Szpak return neta_ppio_enable(priv->ppio); 240*4ccc8d77SZyta Szpak } 241*4ccc8d77SZyta Szpak 242*4ccc8d77SZyta Szpak /** 243*4ccc8d77SZyta Szpak * DPDK callback to bring the link down. 244*4ccc8d77SZyta Szpak * 245*4ccc8d77SZyta Szpak * @param dev 246*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 247*4ccc8d77SZyta Szpak * 248*4ccc8d77SZyta Szpak * @return 249*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 250*4ccc8d77SZyta Szpak */ 251*4ccc8d77SZyta Szpak static int 252*4ccc8d77SZyta Szpak mvneta_dev_set_link_down(struct rte_eth_dev *dev) 253*4ccc8d77SZyta Szpak { 254*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 255*4ccc8d77SZyta Szpak 256*4ccc8d77SZyta Szpak if (!priv->ppio) 257*4ccc8d77SZyta Szpak return 0; 258*4ccc8d77SZyta Szpak 259*4ccc8d77SZyta Szpak return neta_ppio_disable(priv->ppio); 260*4ccc8d77SZyta Szpak } 261*4ccc8d77SZyta Szpak 262*4ccc8d77SZyta Szpak /** 263*4ccc8d77SZyta Szpak * DPDK callback to start the device. 264*4ccc8d77SZyta Szpak * 265*4ccc8d77SZyta Szpak * @param dev 266*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 267*4ccc8d77SZyta Szpak * 268*4ccc8d77SZyta Szpak * @return 269*4ccc8d77SZyta Szpak * 0 on success, negative errno value on failure. 270*4ccc8d77SZyta Szpak */ 271*4ccc8d77SZyta Szpak static int 272*4ccc8d77SZyta Szpak mvneta_dev_start(struct rte_eth_dev *dev) 273*4ccc8d77SZyta Szpak { 274*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 275*4ccc8d77SZyta Szpak char match[MVNETA_MATCH_LEN]; 276*4ccc8d77SZyta Szpak int ret = 0, i; 277*4ccc8d77SZyta Szpak 278*4ccc8d77SZyta Szpak if (priv->ppio) 279*4ccc8d77SZyta Szpak return mvneta_dev_set_link_up(dev); 280*4ccc8d77SZyta Szpak 281*4ccc8d77SZyta Szpak snprintf(match, sizeof(match), "%s", dev->data->name); 282*4ccc8d77SZyta Szpak priv->ppio_params.match = match; 283*4ccc8d77SZyta Szpak priv->ppio_params.inqs_params.mtu = dev->data->mtu; 284*4ccc8d77SZyta Szpak 285*4ccc8d77SZyta Szpak ret = neta_ppio_init(&priv->ppio_params, &priv->ppio); 286*4ccc8d77SZyta Szpak if (ret) { 287*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, "Failed to init ppio"); 288*4ccc8d77SZyta Szpak return ret; 289*4ccc8d77SZyta Szpak } 290*4ccc8d77SZyta Szpak priv->ppio_id = priv->ppio->port_id; 291*4ccc8d77SZyta Szpak 292*4ccc8d77SZyta Szpak /* 293*4ccc8d77SZyta Szpak * In case there are some some stale uc/mc mac addresses flush them 294*4ccc8d77SZyta Szpak * here. It cannot be done during mvneta_dev_close() as port information 295*4ccc8d77SZyta Szpak * is already gone at that point (due to neta_ppio_deinit() in 296*4ccc8d77SZyta Szpak * mvneta_dev_stop()). 297*4ccc8d77SZyta Szpak */ 298*4ccc8d77SZyta Szpak if (!priv->uc_mc_flushed) { 299*4ccc8d77SZyta Szpak ret = neta_ppio_flush_mac_addrs(priv->ppio, 0, 1); 300*4ccc8d77SZyta Szpak if (ret) { 301*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, 302*4ccc8d77SZyta Szpak "Failed to flush uc/mc filter list"); 303*4ccc8d77SZyta Szpak goto out; 304*4ccc8d77SZyta Szpak } 305*4ccc8d77SZyta Szpak priv->uc_mc_flushed = 1; 306*4ccc8d77SZyta Szpak } 307*4ccc8d77SZyta Szpak 308*4ccc8d77SZyta Szpak ret = mvneta_dev_set_link_up(dev); 309*4ccc8d77SZyta Szpak if (ret) { 310*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, "Failed to set link up"); 311*4ccc8d77SZyta Szpak goto out; 312*4ccc8d77SZyta Szpak } 313*4ccc8d77SZyta Szpak 314*4ccc8d77SZyta Szpak /* start tx queues */ 315*4ccc8d77SZyta Szpak for (i = 0; i < dev->data->nb_tx_queues; i++) 316*4ccc8d77SZyta Szpak dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; 317*4ccc8d77SZyta Szpak 318*4ccc8d77SZyta Szpak return 0; 319*4ccc8d77SZyta Szpak 320*4ccc8d77SZyta Szpak out: 321*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, "Failed to start device"); 322*4ccc8d77SZyta Szpak neta_ppio_deinit(priv->ppio); 323*4ccc8d77SZyta Szpak return ret; 324*4ccc8d77SZyta Szpak } 325*4ccc8d77SZyta Szpak 326*4ccc8d77SZyta Szpak /** 327*4ccc8d77SZyta Szpak * DPDK callback to stop the device. 328*4ccc8d77SZyta Szpak * 329*4ccc8d77SZyta Szpak * @param dev 330*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 331*4ccc8d77SZyta Szpak */ 332*4ccc8d77SZyta Szpak static void 333*4ccc8d77SZyta Szpak mvneta_dev_stop(struct rte_eth_dev *dev) 334*4ccc8d77SZyta Szpak { 335*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 336*4ccc8d77SZyta Szpak 337*4ccc8d77SZyta Szpak if (!priv->ppio) 338*4ccc8d77SZyta Szpak return; 339*4ccc8d77SZyta Szpak 340*4ccc8d77SZyta Szpak mvneta_dev_set_link_down(dev); 341*4ccc8d77SZyta Szpak 342*4ccc8d77SZyta Szpak neta_ppio_deinit(priv->ppio); 343*4ccc8d77SZyta Szpak 344*4ccc8d77SZyta Szpak priv->ppio = NULL; 345*4ccc8d77SZyta Szpak } 346*4ccc8d77SZyta Szpak 347*4ccc8d77SZyta Szpak /** 348*4ccc8d77SZyta Szpak * DPDK callback to close the device. 349*4ccc8d77SZyta Szpak * 350*4ccc8d77SZyta Szpak * @param dev 351*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 352*4ccc8d77SZyta Szpak */ 353*4ccc8d77SZyta Szpak static void 354*4ccc8d77SZyta Szpak mvneta_dev_close(struct rte_eth_dev *dev) 355*4ccc8d77SZyta Szpak { 356*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 357*4ccc8d77SZyta Szpak 358*4ccc8d77SZyta Szpak if (priv->ppio) 359*4ccc8d77SZyta Szpak mvneta_dev_stop(dev); 360*4ccc8d77SZyta Szpak } 361*4ccc8d77SZyta Szpak 362*4ccc8d77SZyta Szpak /** 363*4ccc8d77SZyta Szpak * DPDK callback to set the primary MAC address. 364*4ccc8d77SZyta Szpak * 365*4ccc8d77SZyta Szpak * @param dev 366*4ccc8d77SZyta Szpak * Pointer to Ethernet device structure. 367*4ccc8d77SZyta Szpak * @param mac_addr 368*4ccc8d77SZyta Szpak * MAC address to register. 369*4ccc8d77SZyta Szpak */ 370*4ccc8d77SZyta Szpak static int 371*4ccc8d77SZyta Szpak mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) 372*4ccc8d77SZyta Szpak { 373*4ccc8d77SZyta Szpak struct mvneta_priv *priv = dev->data->dev_private; 374*4ccc8d77SZyta Szpak int ret; 375*4ccc8d77SZyta Szpak 376*4ccc8d77SZyta Szpak if (!priv->ppio) 377*4ccc8d77SZyta Szpak return -EINVAL; 378*4ccc8d77SZyta Szpak 379*4ccc8d77SZyta Szpak ret = neta_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes); 380*4ccc8d77SZyta Szpak if (ret) { 381*4ccc8d77SZyta Szpak char buf[ETHER_ADDR_FMT_SIZE]; 382*4ccc8d77SZyta Szpak ether_format_addr(buf, sizeof(buf), mac_addr); 383*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, "Failed to set mac to %s", buf); 384*4ccc8d77SZyta Szpak } 385*4ccc8d77SZyta Szpak return 0; 386*4ccc8d77SZyta Szpak } 387*4ccc8d77SZyta Szpak 388*4ccc8d77SZyta Szpak static const struct eth_dev_ops mvneta_ops = { 389*4ccc8d77SZyta Szpak .dev_configure = mvneta_dev_configure, 390*4ccc8d77SZyta Szpak .dev_start = mvneta_dev_start, 391*4ccc8d77SZyta Szpak .dev_stop = mvneta_dev_stop, 392*4ccc8d77SZyta Szpak .dev_set_link_up = mvneta_dev_set_link_up, 393*4ccc8d77SZyta Szpak .dev_set_link_down = mvneta_dev_set_link_down, 394*4ccc8d77SZyta Szpak .dev_close = mvneta_dev_close, 395*4ccc8d77SZyta Szpak .mac_addr_set = mvneta_mac_addr_set, 396*4ccc8d77SZyta Szpak .dev_infos_get = mvneta_dev_infos_get, 397*4ccc8d77SZyta Szpak .dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get, 398*4ccc8d77SZyta Szpak }; 399*4ccc8d77SZyta Szpak 400*4ccc8d77SZyta Szpak /** 401*4ccc8d77SZyta Szpak * Create device representing Ethernet port. 402*4ccc8d77SZyta Szpak * 403*4ccc8d77SZyta Szpak * @param name 404*4ccc8d77SZyta Szpak * Pointer to the port's name. 405*4ccc8d77SZyta Szpak * 406*4ccc8d77SZyta Szpak * @return 407*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 408*4ccc8d77SZyta Szpak */ 409*4ccc8d77SZyta Szpak static int 410*4ccc8d77SZyta Szpak mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name) 411*4ccc8d77SZyta Szpak { 412*4ccc8d77SZyta Szpak int ret, fd = socket(AF_INET, SOCK_DGRAM, 0); 413*4ccc8d77SZyta Szpak struct rte_eth_dev *eth_dev; 414*4ccc8d77SZyta Szpak struct mvneta_priv *priv; 415*4ccc8d77SZyta Szpak struct ifreq req; 416*4ccc8d77SZyta Szpak 417*4ccc8d77SZyta Szpak eth_dev = rte_eth_dev_allocate(name); 418*4ccc8d77SZyta Szpak if (!eth_dev) 419*4ccc8d77SZyta Szpak return -ENOMEM; 420*4ccc8d77SZyta Szpak 421*4ccc8d77SZyta Szpak priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id()); 422*4ccc8d77SZyta Szpak if (!priv) { 423*4ccc8d77SZyta Szpak ret = -ENOMEM; 424*4ccc8d77SZyta Szpak goto out_free_dev; 425*4ccc8d77SZyta Szpak } 426*4ccc8d77SZyta Szpak 427*4ccc8d77SZyta Szpak eth_dev->data->mac_addrs = 428*4ccc8d77SZyta Szpak rte_zmalloc("mac_addrs", 429*4ccc8d77SZyta Szpak ETHER_ADDR_LEN * MVNETA_MAC_ADDRS_MAX, 0); 430*4ccc8d77SZyta Szpak if (!eth_dev->data->mac_addrs) { 431*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, "Failed to allocate space for eth addrs"); 432*4ccc8d77SZyta Szpak ret = -ENOMEM; 433*4ccc8d77SZyta Szpak goto out_free_priv; 434*4ccc8d77SZyta Szpak } 435*4ccc8d77SZyta Szpak 436*4ccc8d77SZyta Szpak memset(&req, 0, sizeof(req)); 437*4ccc8d77SZyta Szpak strcpy(req.ifr_name, name); 438*4ccc8d77SZyta Szpak ret = ioctl(fd, SIOCGIFHWADDR, &req); 439*4ccc8d77SZyta Szpak if (ret) 440*4ccc8d77SZyta Szpak goto out_free_mac; 441*4ccc8d77SZyta Szpak 442*4ccc8d77SZyta Szpak memcpy(eth_dev->data->mac_addrs[0].addr_bytes, 443*4ccc8d77SZyta Szpak req.ifr_addr.sa_data, ETHER_ADDR_LEN); 444*4ccc8d77SZyta Szpak 445*4ccc8d77SZyta Szpak eth_dev->data->kdrv = RTE_KDRV_NONE; 446*4ccc8d77SZyta Szpak eth_dev->data->dev_private = priv; 447*4ccc8d77SZyta Szpak eth_dev->device = &vdev->device; 448*4ccc8d77SZyta Szpak eth_dev->dev_ops = &mvneta_ops; 449*4ccc8d77SZyta Szpak 450*4ccc8d77SZyta Szpak rte_eth_dev_probing_finish(eth_dev); 451*4ccc8d77SZyta Szpak return 0; 452*4ccc8d77SZyta Szpak out_free_mac: 453*4ccc8d77SZyta Szpak rte_free(eth_dev->data->mac_addrs); 454*4ccc8d77SZyta Szpak out_free_priv: 455*4ccc8d77SZyta Szpak rte_free(priv); 456*4ccc8d77SZyta Szpak out_free_dev: 457*4ccc8d77SZyta Szpak rte_eth_dev_release_port(eth_dev); 458*4ccc8d77SZyta Szpak 459*4ccc8d77SZyta Szpak return ret; 460*4ccc8d77SZyta Szpak } 461*4ccc8d77SZyta Szpak 462*4ccc8d77SZyta Szpak /** 463*4ccc8d77SZyta Szpak * Cleanup previously created device representing Ethernet port. 464*4ccc8d77SZyta Szpak * 465*4ccc8d77SZyta Szpak * @param eth_dev 466*4ccc8d77SZyta Szpak * Pointer to the corresponding rte_eth_dev structure. 467*4ccc8d77SZyta Szpak */ 468*4ccc8d77SZyta Szpak static void 469*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev) 470*4ccc8d77SZyta Szpak { 471*4ccc8d77SZyta Szpak rte_free(eth_dev->data->dev_private); 472*4ccc8d77SZyta Szpak rte_free(eth_dev->data->mac_addrs); 473*4ccc8d77SZyta Szpak rte_eth_dev_release_port(eth_dev); 474*4ccc8d77SZyta Szpak } 475*4ccc8d77SZyta Szpak 476*4ccc8d77SZyta Szpak /** 477*4ccc8d77SZyta Szpak * Cleanup previously created device representing Ethernet port. 478*4ccc8d77SZyta Szpak * 479*4ccc8d77SZyta Szpak * @param name 480*4ccc8d77SZyta Szpak * Pointer to the port name. 481*4ccc8d77SZyta Szpak */ 482*4ccc8d77SZyta Szpak static void 483*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy_name(const char *name) 484*4ccc8d77SZyta Szpak { 485*4ccc8d77SZyta Szpak struct rte_eth_dev *eth_dev; 486*4ccc8d77SZyta Szpak 487*4ccc8d77SZyta Szpak eth_dev = rte_eth_dev_allocated(name); 488*4ccc8d77SZyta Szpak if (!eth_dev) 489*4ccc8d77SZyta Szpak return; 490*4ccc8d77SZyta Szpak 491*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy(eth_dev); 492*4ccc8d77SZyta Szpak } 493*4ccc8d77SZyta Szpak 494*4ccc8d77SZyta Szpak /** 495*4ccc8d77SZyta Szpak * DPDK callback to register the virtual device. 496*4ccc8d77SZyta Szpak * 497*4ccc8d77SZyta Szpak * @param vdev 498*4ccc8d77SZyta Szpak * Pointer to the virtual device. 499*4ccc8d77SZyta Szpak * 500*4ccc8d77SZyta Szpak * @return 501*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 502*4ccc8d77SZyta Szpak */ 503*4ccc8d77SZyta Szpak static int 504*4ccc8d77SZyta Szpak rte_pmd_mvneta_probe(struct rte_vdev_device *vdev) 505*4ccc8d77SZyta Szpak { 506*4ccc8d77SZyta Szpak struct rte_kvargs *kvlist; 507*4ccc8d77SZyta Szpak struct mvneta_ifnames ifnames; 508*4ccc8d77SZyta Szpak int ret = -EINVAL; 509*4ccc8d77SZyta Szpak uint32_t i, ifnum; 510*4ccc8d77SZyta Szpak const char *params; 511*4ccc8d77SZyta Szpak 512*4ccc8d77SZyta Szpak params = rte_vdev_device_args(vdev); 513*4ccc8d77SZyta Szpak if (!params) 514*4ccc8d77SZyta Szpak return -EINVAL; 515*4ccc8d77SZyta Szpak 516*4ccc8d77SZyta Szpak kvlist = rte_kvargs_parse(params, valid_args); 517*4ccc8d77SZyta Szpak if (!kvlist) 518*4ccc8d77SZyta Szpak return -EINVAL; 519*4ccc8d77SZyta Szpak 520*4ccc8d77SZyta Szpak ifnum = rte_kvargs_count(kvlist, MVNETA_IFACE_NAME_ARG); 521*4ccc8d77SZyta Szpak if (ifnum > RTE_DIM(ifnames.names)) 522*4ccc8d77SZyta Szpak goto out_free_kvlist; 523*4ccc8d77SZyta Szpak 524*4ccc8d77SZyta Szpak ifnames.idx = 0; 525*4ccc8d77SZyta Szpak rte_kvargs_process(kvlist, MVNETA_IFACE_NAME_ARG, 526*4ccc8d77SZyta Szpak mvneta_ifnames_get, &ifnames); 527*4ccc8d77SZyta Szpak 528*4ccc8d77SZyta Szpak /* 529*4ccc8d77SZyta Szpak * The below system initialization should be done only once, 530*4ccc8d77SZyta Szpak * on the first provided configuration file 531*4ccc8d77SZyta Szpak */ 532*4ccc8d77SZyta Szpak if (mvneta_dev_num) 533*4ccc8d77SZyta Szpak goto init_devices; 534*4ccc8d77SZyta Szpak 535*4ccc8d77SZyta Szpak MVNETA_LOG(INFO, "Perform MUSDK initializations"); 536*4ccc8d77SZyta Szpak 537*4ccc8d77SZyta Szpak ret = rte_mvep_init(MVEP_MOD_T_NETA, kvlist); 538*4ccc8d77SZyta Szpak if (ret) 539*4ccc8d77SZyta Szpak goto out_free_kvlist; 540*4ccc8d77SZyta Szpak 541*4ccc8d77SZyta Szpak ret = mvneta_neta_init(); 542*4ccc8d77SZyta Szpak if (ret) { 543*4ccc8d77SZyta Szpak MVNETA_LOG(ERR, "Failed to init NETA!"); 544*4ccc8d77SZyta Szpak rte_mvep_deinit(MVEP_MOD_T_NETA); 545*4ccc8d77SZyta Szpak goto out_free_kvlist; 546*4ccc8d77SZyta Szpak } 547*4ccc8d77SZyta Szpak 548*4ccc8d77SZyta Szpak init_devices: 549*4ccc8d77SZyta Szpak for (i = 0; i < ifnum; i++) { 550*4ccc8d77SZyta Szpak MVNETA_LOG(INFO, "Creating %s", ifnames.names[i]); 551*4ccc8d77SZyta Szpak ret = mvneta_eth_dev_create(vdev, ifnames.names[i]); 552*4ccc8d77SZyta Szpak if (ret) 553*4ccc8d77SZyta Szpak goto out_cleanup; 554*4ccc8d77SZyta Szpak } 555*4ccc8d77SZyta Szpak mvneta_dev_num += ifnum; 556*4ccc8d77SZyta Szpak 557*4ccc8d77SZyta Szpak rte_kvargs_free(kvlist); 558*4ccc8d77SZyta Szpak 559*4ccc8d77SZyta Szpak return 0; 560*4ccc8d77SZyta Szpak out_cleanup: 561*4ccc8d77SZyta Szpak for (; i > 0; i--) 562*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy_name(ifnames.names[i]); 563*4ccc8d77SZyta Szpak 564*4ccc8d77SZyta Szpak if (mvneta_dev_num == 0) { 565*4ccc8d77SZyta Szpak mvneta_neta_deinit(); 566*4ccc8d77SZyta Szpak rte_mvep_deinit(MVEP_MOD_T_NETA); 567*4ccc8d77SZyta Szpak } 568*4ccc8d77SZyta Szpak out_free_kvlist: 569*4ccc8d77SZyta Szpak rte_kvargs_free(kvlist); 570*4ccc8d77SZyta Szpak 571*4ccc8d77SZyta Szpak return ret; 572*4ccc8d77SZyta Szpak } 573*4ccc8d77SZyta Szpak 574*4ccc8d77SZyta Szpak /** 575*4ccc8d77SZyta Szpak * DPDK callback to remove virtual device. 576*4ccc8d77SZyta Szpak * 577*4ccc8d77SZyta Szpak * @param vdev 578*4ccc8d77SZyta Szpak * Pointer to the removed virtual device. 579*4ccc8d77SZyta Szpak * 580*4ccc8d77SZyta Szpak * @return 581*4ccc8d77SZyta Szpak * 0 on success, negative error value otherwise. 582*4ccc8d77SZyta Szpak */ 583*4ccc8d77SZyta Szpak static int 584*4ccc8d77SZyta Szpak rte_pmd_mvneta_remove(struct rte_vdev_device *vdev) 585*4ccc8d77SZyta Szpak { 586*4ccc8d77SZyta Szpak int i; 587*4ccc8d77SZyta Szpak const char *name; 588*4ccc8d77SZyta Szpak 589*4ccc8d77SZyta Szpak name = rte_vdev_device_name(vdev); 590*4ccc8d77SZyta Szpak if (!name) 591*4ccc8d77SZyta Szpak return -EINVAL; 592*4ccc8d77SZyta Szpak 593*4ccc8d77SZyta Szpak MVNETA_LOG(INFO, "Removing %s", name); 594*4ccc8d77SZyta Szpak 595*4ccc8d77SZyta Szpak RTE_ETH_FOREACH_DEV(i) { 596*4ccc8d77SZyta Szpak if (rte_eth_devices[i].device != &vdev->device) 597*4ccc8d77SZyta Szpak continue; 598*4ccc8d77SZyta Szpak 599*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy(&rte_eth_devices[i]); 600*4ccc8d77SZyta Szpak mvneta_dev_num--; 601*4ccc8d77SZyta Szpak } 602*4ccc8d77SZyta Szpak 603*4ccc8d77SZyta Szpak if (mvneta_dev_num == 0) { 604*4ccc8d77SZyta Szpak MVNETA_LOG(INFO, "Perform MUSDK deinit"); 605*4ccc8d77SZyta Szpak mvneta_neta_deinit(); 606*4ccc8d77SZyta Szpak rte_mvep_deinit(MVEP_MOD_T_NETA); 607*4ccc8d77SZyta Szpak } 608*4ccc8d77SZyta Szpak 609*4ccc8d77SZyta Szpak return 0; 610*4ccc8d77SZyta Szpak } 611*4ccc8d77SZyta Szpak 612*4ccc8d77SZyta Szpak static struct rte_vdev_driver pmd_mvneta_drv = { 613*4ccc8d77SZyta Szpak .probe = rte_pmd_mvneta_probe, 614*4ccc8d77SZyta Szpak .remove = rte_pmd_mvneta_remove, 615*4ccc8d77SZyta Szpak }; 616*4ccc8d77SZyta Szpak 617*4ccc8d77SZyta Szpak RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv); 618*4ccc8d77SZyta Szpak RTE_PMD_REGISTER_PARAM_STRING(net_mvneta, "iface=<ifc>"); 619*4ccc8d77SZyta Szpak 620*4ccc8d77SZyta Szpak RTE_INIT(mvneta_init_log) 621*4ccc8d77SZyta Szpak { 622*4ccc8d77SZyta Szpak mvneta_logtype = rte_log_register("pmd.net.mvneta"); 623*4ccc8d77SZyta Szpak if (mvneta_logtype >= 0) 624*4ccc8d77SZyta Szpak rte_log_set_level(mvneta_logtype, RTE_LOG_NOTICE); 625*4ccc8d77SZyta Szpak } 626