X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Focteontx%2Focteontx_ethdev.c;h=76c69294d01fe5e6d7b71197659599e56e7ca9b7;hb=c6d1a552a8798df02bf85627c5d47a28ccdc62f8;hp=f2893faa96779350fbb2d01e35392451f3cbef0e;hpb=a371fd7903f99753d535b31dbad2adcc33dcdd5c;p=dpdk.git diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c index f2893faa96..76c69294d0 100644 --- a/drivers/net/octeontx/octeontx_ethdev.c +++ b/drivers/net/octeontx/octeontx_ethdev.c @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -18,12 +20,15 @@ #include #include #include -#include #include "octeontx_ethdev.h" #include "octeontx_rxtx.h" #include "octeontx_logs.h" +struct evdev_priv_data { + OFFLOAD_FLAGS; /*Sequence should not be changed */ +} __rte_cache_aligned; + struct octeontx_vdev_init_params { uint8_t nr_port; }; @@ -42,26 +47,9 @@ enum octeontx_link_speed { OCTEONTX_LINK_SPEED_RESERVE2 }; -int otx_net_logtype_mbox; -int otx_net_logtype_init; -int otx_net_logtype_driver; - -RTE_INIT(otx_net_init_log); -static void -otx_net_init_log(void) -{ - otx_net_logtype_mbox = rte_log_register("pmd.net.octeontx.mbox"); - if (otx_net_logtype_mbox >= 0) - rte_log_set_level(otx_net_logtype_mbox, RTE_LOG_NOTICE); - - otx_net_logtype_init = rte_log_register("pmd.net.octeontx.init"); - if (otx_net_logtype_init >= 0) - rte_log_set_level(otx_net_logtype_init, RTE_LOG_NOTICE); - - otx_net_logtype_driver = rte_log_register("pmd.net.octeontx.driver"); - if (otx_net_logtype_driver >= 0) - rte_log_set_level(otx_net_logtype_driver, RTE_LOG_NOTICE); -} +RTE_LOG_REGISTER(otx_net_logtype_mbox, pmd.net.octeontx.mbox, NOTICE); +RTE_LOG_REGISTER(otx_net_logtype_init, pmd.net.octeontx.init, NOTICE); +RTE_LOG_REGISTER(otx_net_logtype_driver, pmd.net.octeontx.driver, NOTICE); /* Parse integer from integer argument */ static int @@ -119,6 +107,7 @@ static int octeontx_port_open(struct octeontx_nic *nic) { octeontx_mbox_bgx_port_conf_t bgx_port_conf; + octeontx_mbox_bgx_port_fifo_cfg_t fifo_cfg; int res; res = 0; @@ -137,24 +126,126 @@ octeontx_port_open(struct octeontx_nic *nic) nic->base_ochan = bgx_port_conf.base_chan; nic->num_ichans = bgx_port_conf.num_chans; nic->num_ochans = bgx_port_conf.num_chans; - nic->mtu = bgx_port_conf.mtu; + nic->bgx_mtu = bgx_port_conf.mtu; nic->bpen = bgx_port_conf.bpen; nic->fcs_strip = bgx_port_conf.fcs_strip; nic->bcast_mode = bgx_port_conf.bcast_mode; nic->mcast_mode = bgx_port_conf.mcast_mode; nic->speed = bgx_port_conf.mode; - memcpy(&nic->mac_addr[0], &bgx_port_conf.macaddr[0], ETHER_ADDR_LEN); + memset(&fifo_cfg, 0x0, sizeof(fifo_cfg)); + + res = octeontx_bgx_port_get_fifo_cfg(nic->port_id, &fifo_cfg); + if (res < 0) { + octeontx_log_err("failed to get port %d fifo cfg", res); + return res; + } + + nic->fc.rx_fifosz = fifo_cfg.rx_fifosz; + + memcpy(&nic->mac_addr[0], &bgx_port_conf.macaddr[0], + RTE_ETHER_ADDR_LEN); octeontx_log_dbg("port opened %d", nic->port_id); return res; } +static void +octeontx_link_status_print(struct rte_eth_dev *eth_dev, + struct rte_eth_link *link) +{ + if (link && link->link_status) + octeontx_log_info("Port %u: Link Up - speed %u Mbps - %s", + (eth_dev->data->port_id), + link->link_speed, + link->link_duplex == ETH_LINK_FULL_DUPLEX ? + "full-duplex" : "half-duplex"); + else + octeontx_log_info("Port %d: Link Down", + (int)(eth_dev->data->port_id)); +} + +static void +octeontx_link_status_update(struct octeontx_nic *nic, + struct rte_eth_link *link) +{ + memset(link, 0, sizeof(*link)); + + link->link_status = nic->link_up ? ETH_LINK_UP : ETH_LINK_DOWN; + + switch (nic->speed) { + case OCTEONTX_LINK_SPEED_SGMII: + link->link_speed = ETH_SPEED_NUM_1G; + break; + + case OCTEONTX_LINK_SPEED_XAUI: + link->link_speed = ETH_SPEED_NUM_10G; + break; + + case OCTEONTX_LINK_SPEED_RXAUI: + case OCTEONTX_LINK_SPEED_10G_R: + link->link_speed = ETH_SPEED_NUM_10G; + break; + case OCTEONTX_LINK_SPEED_QSGMII: + link->link_speed = ETH_SPEED_NUM_5G; + break; + case OCTEONTX_LINK_SPEED_40G_R: + link->link_speed = ETH_SPEED_NUM_40G; + break; + + case OCTEONTX_LINK_SPEED_RESERVE1: + case OCTEONTX_LINK_SPEED_RESERVE2: + default: + link->link_speed = ETH_SPEED_NUM_NONE; + octeontx_log_err("incorrect link speed %d", nic->speed); + break; + } + + link->link_duplex = ETH_LINK_FULL_DUPLEX; + link->link_autoneg = ETH_LINK_AUTONEG; +} + +static void +octeontx_link_status_poll(void *arg) +{ + struct octeontx_nic *nic = arg; + struct rte_eth_link link; + struct rte_eth_dev *dev; + int res; + + PMD_INIT_FUNC_TRACE(); + + dev = nic->dev; + + res = octeontx_bgx_port_link_status(nic->port_id); + if (res < 0) { + octeontx_log_err("Failed to get port %d link status", + nic->port_id); + } else { + if (nic->link_up != (uint8_t)res) { + nic->link_up = (uint8_t)res; + octeontx_link_status_update(nic, &link); + octeontx_link_status_print(dev, &link); + rte_eth_linkstatus_set(dev, &link); + _rte_eth_dev_callback_process(dev, + RTE_ETH_EVENT_INTR_LSC, + NULL); + } + } + + res = rte_eal_alarm_set(OCCTX_INTR_POLL_INTERVAL_MS * 1000, + octeontx_link_status_poll, nic); + if (res < 0) + octeontx_log_err("Failed to restart alarm for port %d, err: %d", + nic->port_id, res); +} + static void octeontx_port_close(struct octeontx_nic *nic) { PMD_INIT_FUNC_TRACE(); + rte_eal_alarm_cancel(octeontx_link_status_poll, nic); octeontx_bgx_port_close(nic->port_id); octeontx_log_dbg("port closed %d", nic->port_id); } @@ -175,7 +266,7 @@ octeontx_port_stop(struct octeontx_nic *nic) return octeontx_bgx_port_stop(nic->port_id); } -static void +static int octeontx_port_promisc_set(struct octeontx_nic *nic, int en) { struct rte_eth_dev *dev; @@ -186,15 +277,19 @@ octeontx_port_promisc_set(struct octeontx_nic *nic, int en) dev = nic->dev; res = octeontx_bgx_port_promisc_set(nic->port_id, en); - if (res < 0) + if (res < 0) { octeontx_log_err("failed to set promiscuous mode %d", nic->port_id); + return res; + } /* Set proper flag for the mode */ dev->data->promiscuous = (en != 0) ? 1 : 0; octeontx_log_dbg("port %d : promiscuous mode %s", nic->port_id, en ? "set" : "unset"); + + return 0; } static int @@ -225,12 +320,12 @@ octeontx_port_stats(struct octeontx_nic *nic, struct rte_eth_stats *stats) return 0; } -static void +static int octeontx_port_stats_clr(struct octeontx_nic *nic) { PMD_INIT_FUNC_TRACE(); - octeontx_bgx_port_stats_clr(nic->port_id); + return octeontx_bgx_port_stats_clr(nic->port_id); } static inline void @@ -254,6 +349,57 @@ devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf, info->max_num_events; } +static uint16_t +octeontx_tx_offload_flags(struct rte_eth_dev *eth_dev) +{ + struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); + uint16_t flags = 0; + + if (nic->tx_offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM || + nic->tx_offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) + flags |= OCCTX_TX_OFFLOAD_OL3_OL4_CSUM_F; + + if (nic->tx_offloads & DEV_TX_OFFLOAD_IPV4_CKSUM || + nic->tx_offloads & DEV_TX_OFFLOAD_TCP_CKSUM || + nic->tx_offloads & DEV_TX_OFFLOAD_UDP_CKSUM || + nic->tx_offloads & DEV_TX_OFFLOAD_SCTP_CKSUM) + flags |= OCCTX_TX_OFFLOAD_L3_L4_CSUM_F; + + if (!(nic->tx_offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE)) + flags |= OCCTX_TX_OFFLOAD_MBUF_NOFF_F; + + if (nic->tx_offloads & DEV_TX_OFFLOAD_MULTI_SEGS) + flags |= OCCTX_TX_MULTI_SEG_F; + + return flags; +} + +static uint16_t +octeontx_rx_offload_flags(struct rte_eth_dev *eth_dev) +{ + struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); + uint16_t flags = 0; + + if (nic->rx_offloads & (DEV_RX_OFFLOAD_TCP_CKSUM | + DEV_RX_OFFLOAD_UDP_CKSUM)) + flags |= OCCTX_RX_OFFLOAD_CSUM_F; + + if (nic->rx_offloads & (DEV_RX_OFFLOAD_IPV4_CKSUM | + DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)) + flags |= OCCTX_RX_OFFLOAD_CSUM_F; + + if (nic->rx_offloads & DEV_RX_OFFLOAD_SCATTER) { + flags |= OCCTX_RX_MULTI_SEG_F; + eth_dev->data->scattered_rx = 1; + /* If scatter mode is enabled, TX should also be in multi + * seg mode, else memory leak will occur + */ + nic->tx_offloads |= DEV_TX_OFFLOAD_MULTI_SEGS; + } + + return flags; +} + static int octeontx_dev_configure(struct rte_eth_dev *dev) { @@ -283,34 +429,9 @@ octeontx_dev_configure(struct rte_eth_dev *dev) return -EINVAL; } - if (!rxmode->hw_strip_crc) { - PMD_INIT_LOG(NOTICE, "can't disable hw crc strip"); - rxmode->hw_strip_crc = 1; - } - - if (rxmode->hw_ip_checksum) { - PMD_INIT_LOG(NOTICE, "rxcksum not supported"); - rxmode->hw_ip_checksum = 0; - } - - if (rxmode->split_hdr_size) { - octeontx_log_err("rxmode does not support split header"); - return -EINVAL; - } - - if (rxmode->hw_vlan_filter) { - octeontx_log_err("VLAN filter not supported"); - return -EINVAL; - } - - if (rxmode->hw_vlan_extend) { - octeontx_log_err("VLAN extended not supported"); - return -EINVAL; - } - - if (rxmode->enable_lro) { - octeontx_log_err("LRO not supported"); - return -EINVAL; + if (!(txmode->offloads & DEV_TX_OFFLOAD_MT_LOCKFREE)) { + PMD_INIT_LOG(NOTICE, "cant disable lockfree tx"); + txmode->offloads |= DEV_TX_OFFLOAD_MT_LOCKFREE; } if (conf->link_speeds & ETH_LINK_SPEED_FIXED) { @@ -330,7 +451,7 @@ octeontx_dev_configure(struct rte_eth_dev *dev) nic->num_tx_queues = dev->data->nb_tx_queues; - ret = octeontx_pko_channel_open(nic->port_id * PKO_VF_NUM_DQ, + ret = octeontx_pko_channel_open(nic->pko_vfid * PKO_VF_NUM_DQ, nic->num_tx_queues, nic->base_ochan); if (ret) { @@ -339,10 +460,21 @@ octeontx_dev_configure(struct rte_eth_dev *dev) return -EFAULT; } + ret = octeontx_dev_vlan_offload_init(dev); + if (ret) { + octeontx_log_err("failed to initialize vlan offload"); + return -EFAULT; + } + nic->pki.classifier_enable = false; nic->pki.hash_enable = true; nic->pki.initialized = false; + nic->rx_offloads |= rxmode->offloads; + nic->tx_offloads |= txmode->offloads; + nic->rx_offload_flags |= octeontx_rx_offload_flags(dev); + nic->tx_offload_flags |= octeontx_tx_offload_flags(dev); + return 0; } @@ -358,6 +490,10 @@ octeontx_dev_close(struct rte_eth_dev *dev) rte_event_dev_close(nic->evdev); + octeontx_dev_flow_ctrl_fini(dev); + + octeontx_dev_vlan_offload_fini(dev); + ret = octeontx_pko_channel_close(nic->base_ochan); if (ret < 0) { octeontx_log_err("failed to close channel %d VF%d %d %d", @@ -372,21 +508,127 @@ octeontx_dev_close(struct rte_eth_dev *dev) rte_free(txq); } + + /* Free MAC address table */ + rte_free(dev->data->mac_addrs); + dev->data->mac_addrs = NULL; + + octeontx_port_close(nic); + + dev->tx_pkt_burst = NULL; + dev->rx_pkt_burst = NULL; +} + +static int +octeontx_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu) +{ + uint32_t buffsz, frame_size = mtu + OCCTX_L2_OVERHEAD; + struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); + struct rte_eth_dev_data *data = eth_dev->data; + int rc = 0; + + /* Check if MTU is within the allowed range */ + if (frame_size < OCCTX_MIN_FRS || frame_size > OCCTX_MAX_FRS) + return -EINVAL; + + buffsz = data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM; + + /* Refuse MTU that requires the support of scattered packets + * when this feature has not been enabled before. + */ + if (data->dev_started && frame_size > buffsz && + !(nic->rx_offloads & DEV_RX_OFFLOAD_SCATTER)) { + octeontx_log_err("Scatter mode is disabled"); + return -EINVAL; + } + + /* Check * >= max_frame */ + if ((nic->rx_offloads & DEV_RX_OFFLOAD_SCATTER) && + (frame_size > buffsz * OCCTX_RX_NB_SEG_MAX)) + return -EINVAL; + + rc = octeontx_pko_send_mtu(nic->port_id, frame_size); + if (rc) + return rc; + + rc = octeontx_bgx_port_mtu_set(nic->port_id, frame_size); + if (rc) + return rc; + + if (frame_size > RTE_ETHER_MAX_LEN) + nic->rx_offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; + else + nic->rx_offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME; + + /* Update max_rx_pkt_len */ + data->dev_conf.rxmode.max_rx_pkt_len = frame_size; + octeontx_log_info("Received pkt beyond maxlen %d will be dropped", + frame_size); + + return rc; +} + +static int +octeontx_recheck_rx_offloads(struct octeontx_rxq *rxq) +{ + struct rte_eth_dev *eth_dev = rxq->eth_dev; + struct octeontx_nic *nic = octeontx_pmd_priv(eth_dev); + struct rte_eth_dev_data *data = eth_dev->data; + struct rte_pktmbuf_pool_private *mbp_priv; + struct evdev_priv_data *evdev_priv; + struct rte_eventdev *dev; + uint32_t buffsz; + + /* Get rx buffer size */ + mbp_priv = rte_mempool_get_priv(rxq->pool); + buffsz = mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM; + + /* Setup scatter mode if needed by jumbo */ + if (data->dev_conf.rxmode.max_rx_pkt_len > buffsz) { + nic->rx_offloads |= DEV_RX_OFFLOAD_SCATTER; + nic->rx_offload_flags |= octeontx_rx_offload_flags(eth_dev); + nic->tx_offload_flags |= octeontx_tx_offload_flags(eth_dev); + } + + /* Sharing offload flags via eventdev priv region */ + dev = &rte_eventdevs[rxq->evdev]; + evdev_priv = dev->data->dev_private; + evdev_priv->rx_offload_flags = nic->rx_offload_flags; + evdev_priv->tx_offload_flags = nic->tx_offload_flags; + + /* Setup MTU based on max_rx_pkt_len */ + nic->mtu = data->dev_conf.rxmode.max_rx_pkt_len - OCCTX_L2_OVERHEAD; + + return 0; } static int octeontx_dev_start(struct rte_eth_dev *dev) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); - int ret; - - ret = 0; + struct octeontx_rxq *rxq; + int ret, i; PMD_INIT_FUNC_TRACE(); + /* Rechecking if any new offload set to update + * rx/tx burst function pointer accordingly. + */ + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + octeontx_recheck_rx_offloads(rxq); + } + + /* Setting up the mtu based on max_rx_pkt_len */ + ret = octeontx_dev_mtu_set(dev, nic->mtu); + if (ret) { + octeontx_log_err("Failed to set default MTU size %d", ret); + goto error; + } + /* * Tx start */ - dev->tx_pkt_burst = octeontx_xmit_pkts; + octeontx_set_tx_function(dev); ret = octeontx_pko_channel_start(nic->base_ochan); if (ret < 0) { octeontx_log_err("fail to conf VF%d no. txq %d chan %d ret %d", @@ -465,41 +707,24 @@ octeontx_dev_stop(struct rte_eth_dev *dev) ret); return; } - - dev->tx_pkt_burst = NULL; - dev->rx_pkt_burst = NULL; } -static void +static int octeontx_dev_promisc_enable(struct rte_eth_dev *dev) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); PMD_INIT_FUNC_TRACE(); - octeontx_port_promisc_set(nic, 1); + return octeontx_port_promisc_set(nic, 1); } -static void +static int octeontx_dev_promisc_disable(struct rte_eth_dev *dev) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); PMD_INIT_FUNC_TRACE(); - octeontx_port_promisc_set(nic, 0); -} - -static inline int -octeontx_atomic_write_link_status(struct rte_eth_dev *dev, - struct rte_eth_link *link) -{ - struct rte_eth_link *dst = &dev->data->dev_link; - struct rte_eth_link *src = link; - - if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, - *(uint64_t *)src) == 0) - return -1; - - return 0; + return octeontx_port_promisc_set(nic, 0); } static int @@ -515,7 +740,10 @@ octeontx_port_link_status(struct octeontx_nic *nic) return res; } - nic->link_up = (uint8_t)res; + if (nic->link_up != (uint8_t)res || nic->print_flag == -1) { + nic->link_up = (uint8_t)res; + nic->print_flag = 1; + } octeontx_log_dbg("port %d link status %d", nic->port_id, nic->link_up); return res; @@ -532,7 +760,6 @@ octeontx_dev_link_update(struct rte_eth_dev *dev, struct rte_eth_link link; int res; - res = 0; PMD_INIT_FUNC_TRACE(); res = octeontx_port_link_status(nic); @@ -541,39 +768,13 @@ octeontx_dev_link_update(struct rte_eth_dev *dev, return res; } - link.link_status = nic->link_up; - - switch (nic->speed) { - case OCTEONTX_LINK_SPEED_SGMII: - link.link_speed = ETH_SPEED_NUM_1G; - break; - - case OCTEONTX_LINK_SPEED_XAUI: - link.link_speed = ETH_SPEED_NUM_10G; - break; - - case OCTEONTX_LINK_SPEED_RXAUI: - case OCTEONTX_LINK_SPEED_10G_R: - link.link_speed = ETH_SPEED_NUM_10G; - break; - case OCTEONTX_LINK_SPEED_QSGMII: - link.link_speed = ETH_SPEED_NUM_5G; - break; - case OCTEONTX_LINK_SPEED_40G_R: - link.link_speed = ETH_SPEED_NUM_40G; - break; - - case OCTEONTX_LINK_SPEED_RESERVE1: - case OCTEONTX_LINK_SPEED_RESERVE2: - default: - octeontx_log_err("incorrect link speed %d", nic->speed); - break; + octeontx_link_status_update(nic, &link); + if (nic->print_flag) { + octeontx_link_status_print(nic->dev, &link); + nic->print_flag = 0; } - link.link_duplex = ETH_LINK_FULL_DUPLEX; - link.link_autoneg = ETH_LINK_AUTONEG; - - return octeontx_atomic_write_link_status(dev, &link); + return rte_eth_linkstatus_set(dev, &link); } static int @@ -585,33 +786,73 @@ octeontx_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) return octeontx_port_stats(nic, stats); } -static void +static int octeontx_dev_stats_reset(struct rte_eth_dev *dev) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); PMD_INIT_FUNC_TRACE(); - octeontx_port_stats_clr(nic); + return octeontx_port_stats_clr(nic); } static void +octeontx_dev_mac_addr_del(struct rte_eth_dev *dev, uint32_t index) +{ + struct octeontx_nic *nic = octeontx_pmd_priv(dev); + int ret; + + ret = octeontx_bgx_port_mac_del(nic->port_id, index); + if (ret != 0) + octeontx_log_err("failed to del MAC address filter on port %d", + nic->port_id); +} + +static int +octeontx_dev_mac_addr_add(struct rte_eth_dev *dev, + struct rte_ether_addr *mac_addr, + uint32_t index, + __rte_unused uint32_t vmdq) +{ + struct octeontx_nic *nic = octeontx_pmd_priv(dev); + int ret; + + ret = octeontx_bgx_port_mac_add(nic->port_id, mac_addr->addr_bytes, + index); + if (ret < 0) { + octeontx_log_err("failed to add MAC address filter on port %d", + nic->port_id); + return ret; + } + + return 0; +} + +static int octeontx_dev_default_mac_addr_set(struct rte_eth_dev *dev, - struct ether_addr *addr) + struct rte_ether_addr *addr) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); int ret; ret = octeontx_bgx_port_mac_set(nic->port_id, addr->addr_bytes); - if (ret != 0) + if (ret == 0) { + /* Update same mac address to BGX CAM table */ + ret = octeontx_bgx_port_mac_add(nic->port_id, addr->addr_bytes, + 0); + } + if (ret < 0) { octeontx_log_err("failed to set MAC address on port %d", - nic->port_id); + nic->port_id); + } + + return ret; } -static void +static int octeontx_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { - RTE_SET_USED(dev); + struct octeontx_nic *nic = octeontx_pmd_priv(dev); /* Autonegotiation may be disabled */ dev_info->speed_capa = ETH_LINK_SPEED_FIXED; @@ -619,28 +860,36 @@ octeontx_dev_info(struct rte_eth_dev *dev, ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G; - dev_info->driver_name = RTE_STR(rte_octeontx_pmd); - dev_info->max_mac_addrs = 1; + /* Min/Max MTU supported */ + dev_info->min_rx_bufsize = OCCTX_MIN_FRS; + dev_info->max_rx_pktlen = OCCTX_MAX_FRS; + dev_info->max_mtu = dev_info->max_rx_pktlen - OCCTX_L2_OVERHEAD; + dev_info->min_mtu = dev_info->min_rx_bufsize - OCCTX_L2_OVERHEAD; + + dev_info->max_mac_addrs = + octeontx_bgx_port_mac_entries_get(nic->port_id); dev_info->max_rx_pktlen = PKI_MAX_PKTLEN; dev_info->max_rx_queues = 1; dev_info->max_tx_queues = PKO_MAX_NUM_DQ; dev_info->min_rx_bufsize = 0; - dev_info->pci_dev = NULL; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_free_thresh = 0, .rx_drop_en = 0, + .offloads = OCTEONTX_RX_OFFLOADS, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_free_thresh = 0, - .txq_flags = - ETH_TXQ_FLAGS_NOMULTSEGS | - ETH_TXQ_FLAGS_NOOFFLOADS | - ETH_TXQ_FLAGS_NOXSUMS, + .offloads = OCTEONTX_TX_OFFLOADS, }; - dev_info->tx_offload_capa = DEV_TX_OFFLOAD_MT_LOCKFREE; + dev_info->rx_offload_capa = OCTEONTX_RX_OFFLOADS; + dev_info->tx_offload_capa = OCTEONTX_TX_OFFLOADS; + dev_info->rx_queue_offload_capa = OCTEONTX_RX_OFFLOADS; + dev_info->tx_queue_offload_capa = OCTEONTX_TX_OFFLOADS; + + return 0; } static void @@ -686,7 +935,7 @@ close_port: return res; } -static int +int octeontx_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); @@ -712,7 +961,7 @@ octeontx_vf_stop_tx_queue(struct rte_eth_dev *dev, struct octeontx_nic *nic, return ret; } -static int +int octeontx_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); @@ -744,7 +993,7 @@ octeontx_dev_tx_queue_release(void *tx_queue) static int octeontx_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, uint16_t nb_desc, unsigned int socket_id, - const struct rte_eth_txconf *tx_conf) + const struct rte_eth_txconf *tx_conf __rte_unused) { struct octeontx_nic *nic = octeontx_pmd_priv(dev); struct octeontx_txq *txq = NULL; @@ -753,9 +1002,8 @@ octeontx_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, RTE_SET_USED(nb_desc); RTE_SET_USED(socket_id); - RTE_SET_USED(tx_conf); - dq_num = (nic->port_id * PKO_VF_NUM_DQ) + qidx; + dq_num = (nic->pko_vfid * PKO_VF_NUM_DQ) + qidx; /* Socket id check */ if (socket_id != (unsigned int)SOCKET_ID_ANY && @@ -823,7 +1071,7 @@ octeontx_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, pki_qos_cfg_t pki_qos; uintptr_t pool; int ret, port; - uint8_t gaura; + uint16_t gaura; unsigned int ev_queues = (nic->ev_queues * nic->port_id) + qidx; unsigned int ev_ports = (nic->ev_ports * nic->port_id) + qidx; @@ -887,10 +1135,11 @@ octeontx_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, pktbuf_conf.mmask.f_cache_mode = 1; pktbuf_conf.wqe_skip = OCTTX_PACKET_WQE_SKIP; - pktbuf_conf.first_skip = OCTTX_PACKET_FIRST_SKIP; + pktbuf_conf.first_skip = OCTTX_PACKET_FIRST_SKIP(mb_pool); pktbuf_conf.later_skip = OCTTX_PACKET_LATER_SKIP; pktbuf_conf.mbuff_size = (mb_pool->elt_size - RTE_PKTMBUF_HEADROOM - + rte_pktmbuf_priv_size(mb_pool) - sizeof(struct rte_mbuf)); pktbuf_conf.cache_mode = PKI_OPC_MODE_STF2_STT; @@ -934,8 +1183,8 @@ octeontx_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, pool = (uintptr_t)mb_pool->pool_id; - /* Get the gpool Id */ - gaura = octeontx_fpa_bufpool_gpool(pool); + /* Get the gaura Id */ + gaura = octeontx_fpa_bufpool_gaura(pool); pki_qos.qpg_qos = PKI_QPG_QOS_NONE; pki_qos.num_entry = 1; @@ -964,9 +1213,12 @@ octeontx_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qidx, rxq->evdev = nic->evdev; rxq->ev_queues = ev_queues; rxq->ev_ports = ev_ports; + rxq->pool = mb_pool; + octeontx_recheck_rx_offloads(rxq); dev->data->rx_queues[qidx] = rxq; dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED; + return 0; } @@ -1019,15 +1271,24 @@ static const struct eth_dev_ops octeontx_dev_ops = { .link_update = octeontx_dev_link_update, .stats_get = octeontx_dev_stats_get, .stats_reset = octeontx_dev_stats_reset, + .mac_addr_remove = octeontx_dev_mac_addr_del, + .mac_addr_add = octeontx_dev_mac_addr_add, .mac_addr_set = octeontx_dev_default_mac_addr_set, + .vlan_offload_set = octeontx_dev_vlan_offload_set, + .vlan_filter_set = octeontx_dev_vlan_filter_set, .tx_queue_start = octeontx_dev_tx_queue_start, .tx_queue_stop = octeontx_dev_tx_queue_stop, .tx_queue_setup = octeontx_dev_tx_queue_setup, .tx_queue_release = octeontx_dev_tx_queue_release, .rx_queue_setup = octeontx_dev_rx_queue_setup, .rx_queue_release = octeontx_dev_rx_queue_release, + .dev_set_link_up = octeontx_dev_set_link_up, + .dev_set_link_down = octeontx_dev_set_link_down, .dev_supported_ptypes_get = octeontx_dev_supported_ptypes_get, + .mtu_set = octeontx_dev_mtu_set, .pool_ops_supported = octeontx_pool_ops, + .flow_ctrl_get = octeontx_dev_flow_ctrl_get, + .flow_ctrl_set = octeontx_dev_flow_ctrl_set, }; /* Create Ethdev interface per BGX LMAC ports */ @@ -1036,11 +1297,13 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, int socket_id) { int res; + size_t pko_vfid; char octtx_name[OCTEONTX_MAX_NAME_LEN]; struct octeontx_nic *nic = NULL; struct rte_eth_dev *eth_dev = NULL; - struct rte_eth_dev_data *data = NULL; + struct rte_eth_dev_data *data; const char *name = rte_vdev_device_name(dev); + int max_entries; PMD_INIT_FUNC_TRACE(); @@ -1050,17 +1313,22 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, if (eth_dev == NULL) return -ENODEV; - eth_dev->tx_pkt_burst = octeontx_xmit_pkts; + eth_dev->dev_ops = &octeontx_dev_ops; + eth_dev->device = &dev->device; + octeontx_set_tx_function(eth_dev); eth_dev->rx_pkt_burst = octeontx_recv_pkts; + rte_eth_dev_probing_finish(eth_dev); return 0; } - data = rte_zmalloc_socket(octtx_name, sizeof(*data), 0, socket_id); - if (data == NULL) { - octeontx_log_err("failed to allocate devdata"); + /* Reserve an ethdev entry */ + eth_dev = rte_eth_dev_allocate(octtx_name); + if (eth_dev == NULL) { + octeontx_log_err("failed to allocate rte_eth_dev"); res = -ENOMEM; goto err; } + data = eth_dev->data; nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id); if (nic == NULL) { @@ -1068,7 +1336,16 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, res = -ENOMEM; goto err; } + data->dev_private = nic; + pko_vfid = octeontx_pko_get_vfid(); + if (pko_vfid == SIZE_MAX) { + octeontx_log_err("failed to get pko vfid"); + res = -ENODEV; + goto err; + } + + nic->pko_vfid = pko_vfid; nic->port_id = port; nic->evdev = evdev; @@ -1084,27 +1361,16 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, goto err; } - /* Reserve an ethdev entry */ - eth_dev = rte_eth_dev_allocate(octtx_name); - if (eth_dev == NULL) { - octeontx_log_err("failed to allocate rte_eth_dev"); - res = -ENOMEM; - goto err; - } - eth_dev->device = &dev->device; eth_dev->intr_handle = NULL; eth_dev->data->kdrv = RTE_KDRV_NONE; eth_dev->data->numa_node = dev->device.numa_node; - rte_memcpy(data, (eth_dev)->data, sizeof(*data)); - data->dev_private = nic; - data->port_id = eth_dev->data->port_id; - snprintf(data->name, sizeof(data->name), "%s", eth_dev->data->name); nic->ev_queues = 1; nic->ev_ports = 1; + nic->print_flag = -1; data->dev_link.link_status = ETH_LINK_DOWN; data->dev_started = 0; @@ -1112,7 +1378,16 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, data->all_multicast = 0; data->scattered_rx = 0; - data->mac_addrs = rte_zmalloc_socket(octtx_name, ETHER_ADDR_LEN, 0, + /* Get maximum number of supported MAC entries */ + max_entries = octeontx_bgx_port_mac_entries_get(nic->port_id); + if (max_entries < 0) { + octeontx_log_err("Failed to get max entries for mac addr"); + res = -ENOTSUP; + goto err; + } + + data->mac_addrs = rte_zmalloc_socket(octtx_name, max_entries * + RTE_ETHER_ADDR_LEN, 0, socket_id); if (data->mac_addrs == NULL) { octeontx_log_err("failed to allocate memory for mac_addrs"); @@ -1120,7 +1395,6 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, goto err; } - eth_dev->data = data; eth_dev->dev_ops = &octeontx_dev_ops; /* Finally save ethdev pointer to the NIC structure */ @@ -1130,34 +1404,47 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev, octeontx_log_err("eth_dev->port_id (%d) is diff to orig (%d)", data->port_id, nic->port_id); res = -EINVAL; + goto free_mac_addrs; + } + + res = rte_eal_alarm_set(OCCTX_INTR_POLL_INTERVAL_MS * 1000, + octeontx_link_status_poll, nic); + if (res) { + octeontx_log_err("Failed to start link polling alarm"); goto err; } /* Update port_id mac to eth_dev */ - memcpy(data->mac_addrs, nic->mac_addr, ETHER_ADDR_LEN); + memcpy(data->mac_addrs, nic->mac_addr, RTE_ETHER_ADDR_LEN); + + /* Update same mac address to BGX CAM table at index 0 */ + octeontx_bgx_port_mac_add(nic->port_id, nic->mac_addr, 0); + + res = octeontx_dev_flow_ctrl_init(eth_dev); + if (res < 0) + goto err; PMD_INIT_LOG(DEBUG, "ethdev info: "); PMD_INIT_LOG(DEBUG, "port %d, port_ena %d ochan %d num_ochan %d tx_q %d", nic->port_id, nic->port_ena, nic->base_ochan, nic->num_ochans, nic->num_tx_queues); - PMD_INIT_LOG(DEBUG, "speed %d mtu %d", nic->speed, nic->mtu); + PMD_INIT_LOG(DEBUG, "speed %d mtu %d", nic->speed, nic->bgx_mtu); rte_octeontx_pchan_map[(nic->base_ochan >> 8) & 0x7] [(nic->base_ochan >> 4) & 0xF] = data->port_id; + rte_eth_dev_probing_finish(eth_dev); return data->port_id; +free_mac_addrs: + rte_free(data->mac_addrs); + data->mac_addrs = NULL; err: if (nic) octeontx_port_close(nic); - if (eth_dev != NULL) { - rte_free(eth_dev->data->mac_addrs); - rte_free(data); - rte_free(nic); - rte_eth_dev_release_port(eth_dev); - } + rte_eth_dev_release_port(eth_dev); return res; } @@ -1182,17 +1469,22 @@ octeontx_remove(struct rte_vdev_device *dev) if (eth_dev == NULL) return -ENODEV; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + rte_eth_dev_release_port(eth_dev); + continue; + } + nic = octeontx_pmd_priv(eth_dev); rte_event_dev_stop(nic->evdev); PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name); - rte_free(eth_dev->data->mac_addrs); - rte_free(eth_dev->data->dev_private); - rte_free(eth_dev->data); rte_eth_dev_release_port(eth_dev); rte_event_dev_close(nic->evdev); } + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + /* Free FC resource */ octeontx_pko_fc_free(); @@ -1210,12 +1502,28 @@ octeontx_probe(struct rte_vdev_device *dev) struct rte_event_dev_config dev_conf; const char *eventdev_name = "event_octeontx"; struct rte_event_dev_info info; + struct rte_eth_dev *eth_dev; struct octeontx_vdev_init_params init_params = { OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT }; dev_name = rte_vdev_device_name(dev); + + if (rte_eal_process_type() == RTE_PROC_SECONDARY && + strlen(rte_vdev_device_args(dev)) == 0) { + eth_dev = rte_eth_dev_attach_secondary(dev_name); + if (!eth_dev) { + PMD_INIT_LOG(ERR, "Failed to probe %s", dev_name); + return -1; + } + /* TODO: request info from primary to set up Rx and Tx */ + eth_dev->dev_ops = &octeontx_dev_ops; + eth_dev->device = &dev->device; + rte_eth_dev_probing_finish(eth_dev); + return 0; + } + res = octeontx_parse_vdev_init_params(&init_params, dev); if (res < 0) return -EINVAL; @@ -1270,15 +1578,8 @@ octeontx_probe(struct rte_vdev_device *dev) res = -EINVAL; goto parse_error; } - if (pnum > qnum) { - /* - * We don't poll on event ports - * that do not have any queues assigned. - */ - pnum = qnum; - PMD_INIT_LOG(INFO, - "reducing number of active event ports to %d", pnum); - } + + /* Enable all queues available */ for (i = 0; i < qnum; i++) { res = rte_event_queue_setup(evdev, i, NULL); if (res < 0) { @@ -1288,6 +1589,7 @@ octeontx_probe(struct rte_vdev_device *dev) } } + /* Enable all ports available */ for (i = 0; i < pnum; i++) { res = rte_event_port_setup(evdev, i, NULL); if (res < 0) { @@ -1296,6 +1598,14 @@ octeontx_probe(struct rte_vdev_device *dev) i, res); goto parse_error; } + } + + /* + * Do 1:1 links for ports & queues. All queues would be mapped to + * one port. If there are more ports than queues, then some ports + * won't be linked to any queue. + */ + for (i = 0; i < qnum; i++) { /* Link one queue to one event port */ qlist = i; res = rte_event_port_link(evdev, i, &qlist, NULL, 1);