X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fqede%2Fqede_ethdev.c;h=323d46e6ebb27df926df64ea48acc5a0c077370d;hb=05b405d581486651305551a9f7295f40388d95db;hp=8b75ca3a72092c7a7c7a466e5dd83c0d88a4aecb;hpb=235cbe4c22728dd70cd9f1fed4b7910d2e07983e;p=dpdk.git diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c index 8b75ca3a72..323d46e6eb 100644 --- a/drivers/net/qede/qede_ethdev.c +++ b/drivers/net/qede/qede_ethdev.c @@ -7,13 +7,8 @@ #include "qede_ethdev.h" #include #include -#include #include -/* Globals */ -int qede_logtype_init; -int qede_logtype_driver; - static const struct qed_eth_ops *qed_ops; static int qede_eth_dev_uninit(struct rte_eth_dev *eth_dev); static int qede_eth_dev_init(struct rte_eth_dev *eth_dev); @@ -125,6 +120,8 @@ static const struct rte_qede_xstats_name_off qede_xstats_strings[] = { offsetof(struct ecore_eth_stats_common, mftag_filter_discards)}, {"rx_mac_filter_discards", offsetof(struct ecore_eth_stats_common, mac_filter_discards)}, + {"rx_gft_filter_drop", + offsetof(struct ecore_eth_stats_common, gft_filter_drop)}, {"rx_hw_buffer_truncates", offsetof(struct ecore_eth_stats_common, brb_truncates)}, {"rx_hw_buffer_discards", @@ -230,9 +227,60 @@ static const struct rte_qede_xstats_name_off qede_rxq_xstats_strings[] = { offsetof(struct qede_rx_queue, rx_alloc_errors)} }; +/* Get FW version string based on fw_size */ +static int +qede_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t fw_size) +{ + struct qede_dev *qdev = dev->data->dev_private; + struct ecore_dev *edev = &qdev->edev; + struct qed_dev_info *info = &qdev->dev_info.common; + static char ver_str[QEDE_PMD_DRV_VER_STR_SIZE]; + size_t size; + + if (IS_PF(edev)) + snprintf(ver_str, QEDE_PMD_DRV_VER_STR_SIZE, "%s", + QEDE_PMD_FW_VERSION); + else + snprintf(ver_str, QEDE_PMD_DRV_VER_STR_SIZE, "%d.%d.%d.%d", + info->fw_major, info->fw_minor, + info->fw_rev, info->fw_eng); + size = strlen(ver_str); + if (size + 1 <= fw_size) /* Add 1 byte for "\0" */ + strlcpy(fw_ver, ver_str, fw_size); + else + return (size + 1); + + snprintf(ver_str + size, (QEDE_PMD_DRV_VER_STR_SIZE - size), + " MFW: %d.%d.%d.%d", + GET_MFW_FIELD(info->mfw_rev, QED_MFW_VERSION_3), + GET_MFW_FIELD(info->mfw_rev, QED_MFW_VERSION_2), + GET_MFW_FIELD(info->mfw_rev, QED_MFW_VERSION_1), + GET_MFW_FIELD(info->mfw_rev, QED_MFW_VERSION_0)); + size = strlen(ver_str); + if (size + 1 <= fw_size) + strlcpy(fw_ver, ver_str, fw_size); + + if (fw_size <= 32) + goto out; + + snprintf(ver_str + size, (QEDE_PMD_DRV_VER_STR_SIZE - size), + " MBI: %d.%d.%d", + GET_MFW_FIELD(info->mbi_version, QED_MBI_VERSION_2), + GET_MFW_FIELD(info->mbi_version, QED_MBI_VERSION_1), + GET_MFW_FIELD(info->mbi_version, QED_MBI_VERSION_0)); + size = strlen(ver_str); + if (size + 1 <= fw_size) + strlcpy(fw_ver, ver_str, fw_size); + +out: + return 0; +} + static void qede_interrupt_action(struct ecore_hwfn *p_hwfn) { + OSAL_SPIN_LOCK(&p_hwfn->spq_lock); ecore_int_sp_dpc((osal_int_ptr_t)(p_hwfn)); + OSAL_SPIN_UNLOCK(&p_hwfn->spq_lock); } static void @@ -265,6 +313,48 @@ qede_interrupt_handler(void *param) DP_ERR(edev, "rte_intr_ack failed\n"); } +static void +qede_assign_rxtx_handlers(struct rte_eth_dev *dev, bool is_dummy) +{ + uint64_t tx_offloads = dev->data->dev_conf.txmode.offloads; + struct qede_dev *qdev = dev->data->dev_private; + struct ecore_dev *edev = &qdev->edev; + bool use_tx_offload = false; + + if (is_dummy) { + dev->rx_pkt_burst = qede_rxtx_pkts_dummy; + dev->tx_pkt_burst = qede_rxtx_pkts_dummy; + return; + } + + if (ECORE_IS_CMT(edev)) { + dev->rx_pkt_burst = qede_recv_pkts_cmt; + dev->tx_pkt_burst = qede_xmit_pkts_cmt; + return; + } + + if (dev->data->lro || dev->data->scattered_rx) { + DP_INFO(edev, "Assigning qede_recv_pkts\n"); + dev->rx_pkt_burst = qede_recv_pkts; + } else { + DP_INFO(edev, "Assigning qede_recv_pkts_regular\n"); + dev->rx_pkt_burst = qede_recv_pkts_regular; + } + + use_tx_offload = !!(tx_offloads & + (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM | /* tunnel */ + DEV_TX_OFFLOAD_TCP_TSO | /* tso */ + DEV_TX_OFFLOAD_VLAN_INSERT)); /* vlan insert */ + + if (use_tx_offload) { + DP_INFO(edev, "Assigning qede_xmit_pkts\n"); + dev->tx_pkt_burst = qede_xmit_pkts; + } else { + DP_INFO(edev, "Assigning qede_xmit_pkts_regular\n"); + dev->tx_pkt_burst = qede_xmit_pkts_regular; + } +} + static void qede_alloc_etherdev(struct qede_dev *qdev, struct qed_dev_eth_info *info) { @@ -272,34 +362,28 @@ qede_alloc_etherdev(struct qede_dev *qdev, struct qed_dev_eth_info *info) qdev->ops = qed_ops; } -static void qede_print_adapter_info(struct qede_dev *qdev) +static void qede_print_adapter_info(struct rte_eth_dev *dev) { + struct qede_dev *qdev = dev->data->dev_private; struct ecore_dev *edev = &qdev->edev; - struct qed_dev_info *info = &qdev->dev_info.common; - static char drv_ver[QEDE_PMD_DRV_VER_STR_SIZE]; static char ver_str[QEDE_PMD_DRV_VER_STR_SIZE]; - DP_INFO(edev, "*********************************\n"); - DP_INFO(edev, " DPDK version:%s\n", rte_version()); - DP_INFO(edev, " Chip details : %s %c%d\n", + DP_INFO(edev, "**************************************************\n"); + DP_INFO(edev, " %-20s: %s\n", "DPDK version", rte_version()); + DP_INFO(edev, " %-20s: %s %c%d\n", "Chip details", ECORE_IS_BB(edev) ? "BB" : "AH", 'A' + edev->chip_rev, (int)edev->chip_metal); - snprintf(ver_str, QEDE_PMD_DRV_VER_STR_SIZE, "%d.%d.%d.%d", - info->fw_major, info->fw_minor, info->fw_rev, info->fw_eng); - snprintf(drv_ver, QEDE_PMD_DRV_VER_STR_SIZE, "%s_%s", - ver_str, QEDE_PMD_VERSION); - DP_INFO(edev, " Driver version : %s\n", drv_ver); - DP_INFO(edev, " Firmware version : %s\n", ver_str); - - snprintf(ver_str, MCP_DRV_VER_STR_SIZE, - "%d.%d.%d.%d", - (info->mfw_rev >> 24) & 0xff, - (info->mfw_rev >> 16) & 0xff, - (info->mfw_rev >> 8) & 0xff, (info->mfw_rev) & 0xff); - DP_INFO(edev, " Management Firmware version : %s\n", ver_str); - DP_INFO(edev, " Firmware file : %s\n", qede_fw_file); - DP_INFO(edev, "*********************************\n"); + snprintf(ver_str, QEDE_PMD_DRV_VER_STR_SIZE, "%s", + QEDE_PMD_DRV_VERSION); + DP_INFO(edev, " %-20s: %s\n", "Driver version", ver_str); + snprintf(ver_str, QEDE_PMD_DRV_VER_STR_SIZE, "%s", + QEDE_PMD_BASE_VERSION); + DP_INFO(edev, " %-20s: %s\n", "Base version", ver_str); + qede_fw_version_get(dev, ver_str, sizeof(ver_str)); + DP_INFO(edev, " %-20s: %s\n", "Firmware version", ver_str); + DP_INFO(edev, " %-20s: %s\n", "Firmware file", qede_fw_file); + DP_INFO(edev, "**************************************************\n"); } static void qede_reset_queue_stats(struct qede_dev *qdev, bool xstats) @@ -434,7 +518,7 @@ int qede_activate_vport(struct rte_eth_dev *eth_dev, bool flg) params.update_vport_active_tx_flg = 1; params.vport_active_rx_flg = flg; params.vport_active_tx_flg = flg; - if (~qdev->enable_tx_switching & flg) { + if ((qdev->enable_tx_switching == false) && (flg == true)) { params.update_tx_switching_flg = 1; params.tx_switching_flg = !flg; } @@ -535,17 +619,16 @@ qed_configure_filter_rx_mode(struct rte_eth_dev *eth_dev, ECORE_ACCEPT_BCAST; if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) { - flags.rx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED; + flags.rx_accept_filter |= (ECORE_ACCEPT_UCAST_UNMATCHED | + ECORE_ACCEPT_MCAST_UNMATCHED); if (IS_VF(edev)) { - flags.tx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED; - DP_INFO(edev, "Enabling Tx unmatched flag for VF\n"); + flags.tx_accept_filter |= + (ECORE_ACCEPT_UCAST_UNMATCHED | + ECORE_ACCEPT_MCAST_UNMATCHED); + DP_INFO(edev, "Enabling Tx unmatched flags for VF\n"); } } else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) { flags.rx_accept_filter |= ECORE_ACCEPT_MCAST_UNMATCHED; - } else if (type == (QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC | - QED_FILTER_RX_MODE_TYPE_PROMISC)) { - flags.rx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED | - ECORE_ACCEPT_MCAST_UNMATCHED; } return ecore_filter_accept_cmd(edev, 0, flags, false, false, @@ -817,6 +900,8 @@ static int qede_vlan_stripping(struct rte_eth_dev *eth_dev, bool flg) } } + qdev->vlan_strip_flg = flg; + DP_INFO(edev, "VLAN stripping %s\n", flg ? "enabled" : "disabled"); return 0; } @@ -944,9 +1029,6 @@ static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) } } - if (mask & ETH_VLAN_EXTEND_MASK) - DP_ERR(edev, "Extend VLAN not supported\n"); - qdev->vlan_offload_mask = mask; DP_INFO(edev, "VLAN offload mask %d\n", mask); @@ -1022,9 +1104,11 @@ static int qede_dev_start(struct rte_eth_dev *eth_dev) PMD_INIT_FUNC_TRACE(edev); /* Update MTU only if it has changed */ - if (eth_dev->data->mtu != qdev->mtu) { - if (qede_update_mtu(eth_dev, qdev->mtu)) + if (qdev->new_mtu && qdev->new_mtu != qdev->mtu) { + if (qede_update_mtu(eth_dev, qdev->new_mtu)) goto err; + qdev->mtu = qdev->new_mtu; + qdev->new_mtu = 0; } /* Configure TPA parameters */ @@ -1044,7 +1128,7 @@ static int qede_dev_start(struct rte_eth_dev *eth_dev) qede_reset_queue_stats(qdev, true); /* Newer SR-IOV PF driver expects RX/TX queues to be started before - * enabling RSS. Hence RSS configuration is deferred upto this point. + * enabling RSS. Hence RSS configuration is deferred up to this point. * Also, we would like to retain similar behavior in PF case, so we * don't do PF/VF specific check here. */ @@ -1056,12 +1140,18 @@ static int qede_dev_start(struct rte_eth_dev *eth_dev) if (qede_activate_vport(eth_dev, true)) goto err; + /* Bring-up the link */ + qede_dev_set_link_state(eth_dev, true); + /* Update link status */ qede_link_update(eth_dev, 0); /* Start/resume traffic */ qede_fastpath_start(edev); + /* Assign I/O handlers */ + qede_assign_rxtx_handlers(eth_dev, false); + DP_INFO(edev, "Device started\n"); return 0; @@ -1070,16 +1160,28 @@ err: return -1; /* common error code is < 0 */ } -static void qede_dev_stop(struct rte_eth_dev *eth_dev) +static int qede_dev_stop(struct rte_eth_dev *eth_dev) { struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); PMD_INIT_FUNC_TRACE(edev); + eth_dev->data->dev_started = 0; + + /* Bring the link down */ + qede_dev_set_link_state(eth_dev, false); + + /* Update link status */ + qede_link_update(eth_dev, 0); + + /* Replace I/O functions with dummy ones. It cannot + * be set to NULL because rte_eth_rx_burst() doesn't check for NULL. + */ + qede_assign_rxtx_handlers(eth_dev, true); /* Disable vport */ if (qede_activate_vport(eth_dev, false)) - return; + return 0; if (qdev->enable_lro) qede_enable_tpa(eth_dev, false); @@ -1091,6 +1193,8 @@ static void qede_dev_stop(struct rte_eth_dev *eth_dev) ecore_hw_stop_fastpath(edev); /* TBD - loop */ DP_INFO(edev, "Device is stopped\n"); + + return 0; } static const char * const valid_args[] = { @@ -1162,10 +1266,15 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev) struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode; + uint8_t num_rxqs; + uint8_t num_txqs; int ret; PMD_INIT_FUNC_TRACE(edev); + if (rxmode->mq_mode & ETH_MQ_RX_RSS_FLAG) + rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH; + /* We need to have min 1 RX queue.There is no min check in * rte_eth_dev_configure(), so we are checking it here. */ @@ -1191,12 +1300,17 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev) if (qede_check_fdir_support(eth_dev)) return -ENOTSUP; - qede_dealloc_fp_resc(eth_dev); - qdev->num_tx_queues = eth_dev->data->nb_tx_queues * edev->num_hwfns; - qdev->num_rx_queues = eth_dev->data->nb_rx_queues * edev->num_hwfns; - - if (qede_alloc_fp_resc(qdev)) - return -ENOMEM; + /* Allocate/reallocate fastpath resources only for new queue config */ + num_txqs = eth_dev->data->nb_tx_queues * edev->num_hwfns; + num_rxqs = eth_dev->data->nb_rx_queues * edev->num_hwfns; + if (qdev->num_tx_queues != num_txqs || + qdev->num_rx_queues != num_rxqs) { + qede_dealloc_fp_resc(eth_dev); + qdev->num_tx_queues = num_txqs; + qdev->num_rx_queues = num_rxqs; + if (qede_alloc_fp_resc(qdev)) + return -ENOMEM; + } /* If jumbo enabled adjust MTU */ if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) @@ -1244,7 +1358,7 @@ static const struct rte_eth_desc_lim qede_tx_desc_lim = { .nb_mtu_seg_max = ETH_TX_MAX_BDS_PER_NON_LSO_PACKET }; -static void +static int qede_dev_info_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *dev_info) { @@ -1286,7 +1400,8 @@ qede_dev_info_get(struct rte_eth_dev *eth_dev, DEV_RX_OFFLOAD_SCATTER | DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_VLAN_FILTER | - DEV_RX_OFFLOAD_VLAN_STRIP); + DEV_RX_OFFLOAD_VLAN_STRIP | + DEV_RX_OFFLOAD_RSS_HASH); dev_info->rx_queue_offload_capa = 0; /* TX offloads are on a per-packet basis, so it is applicable @@ -1328,6 +1443,8 @@ qede_dev_info_get(struct rte_eth_dev *eth_dev, if (link.adv_speed & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) speed_cap |= ETH_LINK_SPEED_100G; dev_info->speed_capa = speed_cap; + + return 0; } /* return 0 means link status changed, -1 means not changed */ @@ -1376,33 +1493,36 @@ qede_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete) return rte_eth_linkstatus_set(eth_dev, &link); } -static void qede_promiscuous_enable(struct rte_eth_dev *eth_dev) +static int qede_promiscuous_enable(struct rte_eth_dev *eth_dev) { - struct qede_dev *qdev = eth_dev->data->dev_private; - struct ecore_dev *edev = &qdev->edev; + enum _ecore_status_t ecore_status; + struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); + struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); enum qed_filter_rx_mode_type type = QED_FILTER_RX_MODE_TYPE_PROMISC; PMD_INIT_FUNC_TRACE(edev); - if (rte_eth_allmulticast_get(eth_dev->data->port_id) == 1) - type |= QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC; + ecore_status = qed_configure_filter_rx_mode(eth_dev, type); - qed_configure_filter_rx_mode(eth_dev, type); + return ecore_status >= ECORE_SUCCESS ? 0 : -EAGAIN; } -static void qede_promiscuous_disable(struct rte_eth_dev *eth_dev) +static int qede_promiscuous_disable(struct rte_eth_dev *eth_dev) { struct qede_dev *qdev = eth_dev->data->dev_private; struct ecore_dev *edev = &qdev->edev; + enum _ecore_status_t ecore_status; PMD_INIT_FUNC_TRACE(edev); if (rte_eth_allmulticast_get(eth_dev->data->port_id) == 1) - qed_configure_filter_rx_mode(eth_dev, + ecore_status = qed_configure_filter_rx_mode(eth_dev, QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC); else - qed_configure_filter_rx_mode(eth_dev, + ecore_status = qed_configure_filter_rx_mode(eth_dev, QED_FILTER_RX_MODE_TYPE_REGULAR); + + return ecore_status >= ECORE_SUCCESS ? 0 : -EAGAIN; } static void qede_poll_sp_sb_cb(void *param) @@ -1424,23 +1544,29 @@ static void qede_poll_sp_sb_cb(void *param) } } -static void qede_dev_close(struct rte_eth_dev *eth_dev) +static int qede_dev_close(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); + int ret = 0; PMD_INIT_FUNC_TRACE(edev); + /* only close in case of the primary process */ + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return 0; + /* dev_stop() shall cleanup fp resources in hw but without releasing * dma memories and sw structures so that dev_start() can be called * by the app without reconfiguration. However, in dev_close() we * can release all the resources and device can be brought up newly */ if (eth_dev->data->dev_started) - qede_dev_stop(eth_dev); + ret = qede_dev_stop(eth_dev); - qede_stop_vport(edev); + if (qdev->vport_started) + qede_stop_vport(edev); qdev->vport_started = false; qede_fdir_dealloc_resc(eth_dev); qede_dealloc_fp_resc(eth_dev); @@ -1448,8 +1574,6 @@ static void qede_dev_close(struct rte_eth_dev *eth_dev) eth_dev->data->nb_rx_queues = 0; eth_dev->data->nb_tx_queues = 0; - /* Bring the link down */ - qede_dev_set_link_state(eth_dev, false); qdev->ops->common->slowpath_stop(edev); qdev->ops->common->remove(edev); rte_intr_disable(&pci_dev->intr_handle); @@ -1469,6 +1593,8 @@ static void qede_dev_close(struct rte_eth_dev *eth_dev) if (ECORE_IS_CMT(edev)) rte_eal_alarm_cancel(qede_poll_sp_sb_cb, (void *)eth_dev); + + return ret; } static int @@ -1477,7 +1603,7 @@ qede_get_stats(struct rte_eth_dev *eth_dev, struct rte_eth_stats *eth_stats) struct qede_dev *qdev = eth_dev->data->dev_private; struct ecore_dev *edev = &qdev->edev; struct ecore_eth_stats stats; - unsigned int i = 0, j = 0, qid; + unsigned int i = 0, j = 0, qid, idx, hw_fn; unsigned int rxq_stat_cntrs, txq_stat_cntrs; struct qede_tx_queue *txq; @@ -1525,32 +1651,47 @@ qede_get_stats(struct rte_eth_dev *eth_dev, struct rte_eth_stats *eth_stats) " appropriately and retry.\n"); for (qid = 0; qid < eth_dev->data->nb_rx_queues; qid++) { - eth_stats->q_ipackets[i] = - *(uint64_t *)( - ((char *)(qdev->fp_array[qid].rxq)) + - offsetof(struct qede_rx_queue, - rcv_pkts)); - eth_stats->q_errors[i] = - *(uint64_t *)( - ((char *)(qdev->fp_array[qid].rxq)) + - offsetof(struct qede_rx_queue, - rx_hw_errors)) + - *(uint64_t *)( - ((char *)(qdev->fp_array[qid].rxq)) + - offsetof(struct qede_rx_queue, - rx_alloc_errors)); + eth_stats->q_ipackets[i] = 0; + eth_stats->q_errors[i] = 0; + + for_each_hwfn(edev, hw_fn) { + idx = qid * edev->num_hwfns + hw_fn; + + eth_stats->q_ipackets[i] += + *(uint64_t *) + (((char *)(qdev->fp_array[idx].rxq)) + + offsetof(struct qede_rx_queue, + rcv_pkts)); + eth_stats->q_errors[i] += + *(uint64_t *) + (((char *)(qdev->fp_array[idx].rxq)) + + offsetof(struct qede_rx_queue, + rx_hw_errors)) + + *(uint64_t *) + (((char *)(qdev->fp_array[idx].rxq)) + + offsetof(struct qede_rx_queue, + rx_alloc_errors)); + } + i++; if (i == rxq_stat_cntrs) break; } for (qid = 0; qid < eth_dev->data->nb_tx_queues; qid++) { - txq = qdev->fp_array[qid].txq; - eth_stats->q_opackets[j] = - *((uint64_t *)(uintptr_t) - (((uint64_t)(uintptr_t)(txq)) + - offsetof(struct qede_tx_queue, - xmit_pkts))); + eth_stats->q_opackets[j] = 0; + + for_each_hwfn(edev, hw_fn) { + idx = qid * edev->num_hwfns + hw_fn; + + txq = qdev->fp_array[idx].txq; + eth_stats->q_opackets[j] += + *((uint64_t *)(uintptr_t) + (((uint64_t)(uintptr_t)(txq)) + + offsetof(struct qede_tx_queue, + xmit_pkts))); + } + j++; if (j == txq_stat_cntrs) break; @@ -1583,42 +1724,43 @@ qede_get_xstats_names(struct rte_eth_dev *dev, struct qede_dev *qdev = dev->data->dev_private; struct ecore_dev *edev = &qdev->edev; const unsigned int stat_cnt = qede_get_xstats_count(qdev); - unsigned int i, qid, stat_idx = 0; - unsigned int rxq_stat_cntrs; + unsigned int i, qid, hw_fn, stat_idx = 0; - if (xstats_names != NULL) { - for (i = 0; i < RTE_DIM(qede_xstats_strings); i++) { + if (xstats_names == NULL) + return stat_cnt; + + for (i = 0; i < RTE_DIM(qede_xstats_strings); i++) { + strlcpy(xstats_names[stat_idx].name, + qede_xstats_strings[i].name, + sizeof(xstats_names[stat_idx].name)); + stat_idx++; + } + + if (ECORE_IS_BB(edev)) { + for (i = 0; i < RTE_DIM(qede_bb_xstats_strings); i++) { strlcpy(xstats_names[stat_idx].name, - qede_xstats_strings[i].name, + qede_bb_xstats_strings[i].name, sizeof(xstats_names[stat_idx].name)); stat_idx++; } - - if (ECORE_IS_BB(edev)) { - for (i = 0; i < RTE_DIM(qede_bb_xstats_strings); i++) { - strlcpy(xstats_names[stat_idx].name, - qede_bb_xstats_strings[i].name, - sizeof(xstats_names[stat_idx].name)); - stat_idx++; - } - } else { - for (i = 0; i < RTE_DIM(qede_ah_xstats_strings); i++) { - strlcpy(xstats_names[stat_idx].name, - qede_ah_xstats_strings[i].name, - sizeof(xstats_names[stat_idx].name)); - stat_idx++; - } + } else { + for (i = 0; i < RTE_DIM(qede_ah_xstats_strings); i++) { + strlcpy(xstats_names[stat_idx].name, + qede_ah_xstats_strings[i].name, + sizeof(xstats_names[stat_idx].name)); + stat_idx++; } + } - rxq_stat_cntrs = RTE_MIN(QEDE_RSS_COUNT(dev), - RTE_ETHDEV_QUEUE_STAT_CNTRS); - for (qid = 0; qid < rxq_stat_cntrs; qid++) { + for (qid = 0; qid < QEDE_RSS_COUNT(dev); qid++) { + for_each_hwfn(edev, hw_fn) { for (i = 0; i < RTE_DIM(qede_rxq_xstats_strings); i++) { snprintf(xstats_names[stat_idx].name, - sizeof(xstats_names[stat_idx].name), - "%.4s%d%s", - qede_rxq_xstats_strings[i].name, qid, - qede_rxq_xstats_strings[i].name + 4); + RTE_ETH_XSTATS_NAME_SIZE, + "%.4s%d.%d%s", + qede_rxq_xstats_strings[i].name, + hw_fn, qid, + qede_rxq_xstats_strings[i].name + 4); stat_idx++; } } @@ -1635,8 +1777,7 @@ qede_get_xstats(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, struct ecore_dev *edev = &qdev->edev; struct ecore_eth_stats stats; const unsigned int num = qede_get_xstats_count(qdev); - unsigned int i, qid, stat_idx = 0; - unsigned int rxq_stat_cntrs; + unsigned int i, qid, hw_fn, fpidx, stat_idx = 0; if (n < num) return num; @@ -1668,22 +1809,24 @@ qede_get_xstats(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, } } - rxq_stat_cntrs = RTE_MIN(QEDE_RSS_COUNT(dev), - RTE_ETHDEV_QUEUE_STAT_CNTRS); - for (qid = 0; qid < rxq_stat_cntrs; qid++) { - for (i = 0; i < RTE_DIM(qede_rxq_xstats_strings); i++) { - xstats[stat_idx].value = *(uint64_t *) - (((char *)(qdev->fp_array[qid].rxq)) + - qede_rxq_xstats_strings[i].offset); - xstats[stat_idx].id = stat_idx; - stat_idx++; + for (qid = 0; qid < dev->data->nb_rx_queues; qid++) { + for_each_hwfn(edev, hw_fn) { + for (i = 0; i < RTE_DIM(qede_rxq_xstats_strings); i++) { + fpidx = qid * edev->num_hwfns + hw_fn; + xstats[stat_idx].value = *(uint64_t *) + (((char *)(qdev->fp_array[fpidx].rxq)) + + qede_rxq_xstats_strings[i].offset); + xstats[stat_idx].id = stat_idx; + stat_idx++; + } + } } return stat_idx; } -static void +static int qede_reset_xstats(struct rte_eth_dev *dev) { struct qede_dev *qdev = dev->data->dev_private; @@ -1691,6 +1834,8 @@ qede_reset_xstats(struct rte_eth_dev *dev) ecore_reset_vport_stats(edev); qede_reset_queue_stats(qdev, true); + + return 0; } int qede_dev_set_link_state(struct rte_eth_dev *eth_dev, bool link_up) @@ -1720,34 +1865,42 @@ static int qede_dev_set_link_down(struct rte_eth_dev *eth_dev) return qede_dev_set_link_state(eth_dev, false); } -static void qede_reset_stats(struct rte_eth_dev *eth_dev) +static int qede_reset_stats(struct rte_eth_dev *eth_dev) { struct qede_dev *qdev = eth_dev->data->dev_private; struct ecore_dev *edev = &qdev->edev; ecore_reset_vport_stats(edev); qede_reset_queue_stats(qdev, false); + + return 0; } -static void qede_allmulticast_enable(struct rte_eth_dev *eth_dev) +static int qede_allmulticast_enable(struct rte_eth_dev *eth_dev) { enum qed_filter_rx_mode_type type = QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC; + enum _ecore_status_t ecore_status; if (rte_eth_promiscuous_get(eth_dev->data->port_id) == 1) - type |= QED_FILTER_RX_MODE_TYPE_PROMISC; + type = QED_FILTER_RX_MODE_TYPE_PROMISC; + ecore_status = qed_configure_filter_rx_mode(eth_dev, type); - qed_configure_filter_rx_mode(eth_dev, type); + return ecore_status >= ECORE_SUCCESS ? 0 : -EAGAIN; } -static void qede_allmulticast_disable(struct rte_eth_dev *eth_dev) +static int qede_allmulticast_disable(struct rte_eth_dev *eth_dev) { + enum _ecore_status_t ecore_status; + if (rte_eth_promiscuous_get(eth_dev->data->port_id) == 1) - qed_configure_filter_rx_mode(eth_dev, + ecore_status = qed_configure_filter_rx_mode(eth_dev, QED_FILTER_RX_MODE_TYPE_PROMISC); else - qed_configure_filter_rx_mode(eth_dev, + ecore_status = qed_configure_filter_rx_mode(eth_dev, QED_FILTER_RX_MODE_TYPE_REGULAR); + + return ecore_status >= ECORE_SUCCESS ? 0 : -EAGAIN; } static int @@ -1932,6 +2085,7 @@ qede_dev_supported_ptypes_get(struct rte_eth_dev *eth_dev) }; if (eth_dev->rx_pkt_burst == qede_recv_pkts || + eth_dev->rx_pkt_burst == qede_recv_pkts_regular || eth_dev->rx_pkt_burst == qede_recv_pkts_cmt) return ptypes; @@ -1982,8 +2136,10 @@ int qede_rss_hash_update(struct rte_eth_dev *eth_dev, /* RSS hash key */ if (key) { if (len > (ECORE_RSS_KEY_SIZE * sizeof(uint32_t))) { - DP_ERR(edev, "RSS key length exceeds limit\n"); - return -EINVAL; + len = ECORE_RSS_KEY_SIZE * sizeof(uint32_t); + DP_NOTICE(edev, false, + "RSS key length too big, trimmed to %d\n", + len); } DP_INFO(edev, "Applying user supplied hash key\n"); rss_params.update_rss_key = 1; @@ -2166,7 +2322,11 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) int i, rc; PMD_INIT_FUNC_TRACE(edev); - qede_dev_info_get(dev, &dev_info); + rc = qede_dev_info_get(dev, &dev_info); + if (rc != 0) { + DP_ERR(edev, "Error during getting ethernet device info\n"); + return rc; + } max_rx_pkt_len = mtu + QEDE_MAX_ETHER_HDR_LEN; frame_size = max_rx_pkt_len; if (mtu < RTE_ETHER_MIN_MTU || frame_size > dev_info.max_rx_pktlen) { @@ -2181,18 +2341,15 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) dev->data->min_rx_buf_size); return -EINVAL; } - /* Temporarily replace I/O functions with dummy ones. It cannot - * be set to NULL because rte_eth_rx_burst() doesn't check for NULL. - */ - dev->rx_pkt_burst = qede_rxtx_pkts_dummy; - dev->tx_pkt_burst = qede_rxtx_pkts_dummy; if (dev->data->dev_started) { dev->data->dev_started = 0; - qede_dev_stop(dev); + rc = qede_dev_stop(dev); + if (rc != 0) + return rc; restart = true; } rte_delay_ms(1000); - qdev->mtu = mtu; + qdev->new_mtu = mtu; /* Fix up RX buf size for all queues of the port */ for (i = 0; i < qdev->num_rx_queues; i++) { @@ -2211,7 +2368,7 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) fp->rxq->rx_buf_size = rc; } } - if (max_rx_pkt_len > RTE_ETHER_MAX_LEN) + if (frame_size > QEDE_ETH_MAX_LEN) dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; else dev->data->dev_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME; @@ -2223,14 +2380,7 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) /* update max frame size */ dev->data->dev_conf.rxmode.max_rx_pkt_len = max_rx_pkt_len; - /* Reassign back */ - if (ECORE_IS_CMT(edev)) { - dev->rx_pkt_burst = qede_recv_pkts_cmt; - dev->tx_pkt_burst = qede_xmit_pkts_cmt; - } else { - dev->rx_pkt_burst = qede_recv_pkts; - dev->tx_pkt_burst = qede_xmit_pkts; - } + return 0; } @@ -2251,7 +2401,6 @@ static const struct eth_dev_ops qede_eth_dev_ops = { .dev_infos_get = qede_dev_info_get, .rx_queue_setup = qede_rx_queue_setup, .rx_queue_release = qede_rx_queue_release, - .rx_descriptor_status = qede_rx_descriptor_status, .tx_queue_setup = qede_tx_queue_setup, .tx_queue_release = qede_tx_queue_release, .dev_start = qede_dev_start, @@ -2284,9 +2433,11 @@ static const struct eth_dev_ops qede_eth_dev_ops = { .reta_update = qede_rss_reta_update, .reta_query = qede_rss_reta_query, .mtu_set = qede_set_mtu, - .filter_ctrl = qede_dev_filter_ctrl, + .flow_ops_get = qede_dev_flow_ops_get, .udp_tunnel_port_add = qede_udp_dst_port_add, .udp_tunnel_port_del = qede_udp_dst_port_del, + .fw_version_get = qede_fw_version_get, + .get_reg = qede_get_regs, }; static const struct eth_dev_ops qede_eth_vf_dev_ops = { @@ -2294,7 +2445,6 @@ static const struct eth_dev_ops qede_eth_vf_dev_ops = { .dev_infos_get = qede_dev_info_get, .rx_queue_setup = qede_rx_queue_setup, .rx_queue_release = qede_rx_queue_release, - .rx_descriptor_status = qede_rx_descriptor_status, .tx_queue_setup = qede_tx_queue_setup, .tx_queue_release = qede_tx_queue_release, .dev_start = qede_dev_start, @@ -2327,6 +2477,7 @@ static const struct eth_dev_ops qede_eth_vf_dev_ops = { .mac_addr_add = qede_mac_addr_add, .mac_addr_remove = qede_mac_addr_remove, .mac_addr_set = qede_mac_addr_set, + .fw_version_get = qede_fw_version_get, }; static void qede_update_pf_params(struct ecore_dev *edev) @@ -2339,6 +2490,24 @@ static void qede_update_pf_params(struct ecore_dev *edev) qed_ops->common->update_pf_params(edev, &pf_params); } +static void qede_generate_random_mac_addr(struct rte_ether_addr *mac_addr) +{ + uint64_t random; + + /* Set Organizationally Unique Identifier (OUI) prefix. */ + mac_addr->addr_bytes[0] = 0x00; + mac_addr->addr_bytes[1] = 0x09; + mac_addr->addr_bytes[2] = 0xC0; + + /* Force indication of locally assigned MAC address. */ + mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR; + + /* Generate the last 3 bytes of the MAC address with a random number. */ + random = rte_rand(); + + memcpy(&mac_addr->addr_bytes[3], &random, 3); +} + static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) { struct rte_pci_device *pci_dev; @@ -2351,7 +2520,7 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) uint8_t bulletin_change; uint8_t vf_mac[RTE_ETHER_ADDR_LEN]; uint8_t is_mac_forced; - bool is_mac_exist; + bool is_mac_exist = false; /* Fix up ecore debug level */ uint32_t dp_module = ~0 & ~ECORE_MSG_HW; uint8_t dp_level = ECORE_LEVEL_VERBOSE; @@ -2377,6 +2546,7 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) } rte_eth_copy_pci_info(eth_dev, pci_dev); + eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; /* @DPDK */ edev->vendor_id = pci_dev->id.vendor_id; @@ -2385,7 +2555,8 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) qed_ops = qed_get_eth_ops(); if (!qed_ops) { DP_ERR(edev, "Failed to get qed_eth_ops_pass\n"); - return -EINVAL; + rc = -EINVAL; + goto err; } DP_INFO(edev, "Starting qede probe\n"); @@ -2393,7 +2564,8 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) dp_level, is_vf); if (rc != 0) { DP_ERR(edev, "qede probe failed rc %d\n", rc); - return -ENODEV; + rc = -ENODEV; + goto err; } qede_update_pf_params(edev); @@ -2414,7 +2586,8 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) if (rte_intr_enable(&pci_dev->intr_handle)) { DP_ERR(edev, "rte_intr_enable() failed\n"); - return -ENODEV; + rc = -ENODEV; + goto err; } /* Start the Slowpath-process */ @@ -2428,14 +2601,7 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) strncpy((char *)params.name, QEDE_PMD_VER_PREFIX, QEDE_PMD_DRV_VER_STR_SIZE); - if (ECORE_IS_CMT(edev)) { - eth_dev->rx_pkt_burst = qede_recv_pkts_cmt; - eth_dev->tx_pkt_burst = qede_xmit_pkts_cmt; - } else { - eth_dev->rx_pkt_burst = qede_recv_pkts; - eth_dev->tx_pkt_burst = qede_xmit_pkts; - } - + qede_assign_rxtx_handlers(eth_dev, true); eth_dev->tx_pkt_prepare = qede_xmit_prep_pkts; /* For CMT mode device do periodic polling for slowpath events. @@ -2449,7 +2615,8 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) if (rc != 0) { DP_ERR(edev, "Unable to start periodic" " timer rc %d\n", rc); - return -EINVAL; + rc = -EINVAL; + goto err; } } @@ -2458,7 +2625,8 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) DP_ERR(edev, "Cannot start slowpath rc = %d\n", rc); rte_eal_alarm_cancel(qede_poll_sp_sb_cb, (void *)eth_dev); - return -ENODEV; + rc = -ENODEV; + goto err; } rc = qed_ops->fill_dev_info(edev, &dev_info); @@ -2468,11 +2636,17 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) qed_ops->common->remove(edev); rte_eal_alarm_cancel(qede_poll_sp_sb_cb, (void *)eth_dev); - return -ENODEV; + rc = -ENODEV; + goto err; } qede_alloc_etherdev(adapter, &dev_info); + if (do_once) { + qede_print_adapter_info(eth_dev); + do_once = false; + } + adapter->ops->common->set_name(edev, edev->name); if (!is_vf) @@ -2525,17 +2699,24 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) DP_ERR(edev, "No VF macaddr assigned\n"); } } - } - eth_dev->dev_ops = (is_vf) ? &qede_eth_vf_dev_ops : &qede_eth_dev_ops; + /* If MAC doesn't exist from PF, generate random one */ + if (!is_mac_exist) { + struct rte_ether_addr *mac_addr; - if (do_once) { - qede_print_adapter_info(adapter); - do_once = false; + mac_addr = (struct rte_ether_addr *)&vf_mac; + qede_generate_random_mac_addr(mac_addr); + + rte_ether_addr_copy(mac_addr, + ð_dev->data->mac_addrs[0]); + + rte_ether_addr_copy(ð_dev->data->mac_addrs[0], + &adapter->primary_mac); + } } - /* Bring-up the link */ - qede_dev_set_link_state(eth_dev, true); + eth_dev->dev_ops = (is_vf) ? &qede_eth_vf_dev_ops : &qede_eth_dev_ops; + eth_dev->rx_descriptor_status = qede_rx_descriptor_status; adapter->num_tx_queues = 0; adapter->num_rx_queues = 0; @@ -2566,6 +2747,7 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) adapter->vxlan.enable = false; adapter->geneve.enable = false; adapter->ipgre.enable = false; + qed_ops->sriov_configure(edev, pci_dev->max_vfs); } DP_INFO(edev, "MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -2579,6 +2761,13 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf) DP_INFO(edev, "Device initialized\n"); return 0; + +err: + if (do_once) { + qede_print_adapter_info(eth_dev); + do_once = false; + } + return rc; } static int qedevf_eth_dev_init(struct rte_eth_dev *eth_dev) @@ -2595,20 +2784,8 @@ static int qede_dev_common_uninit(struct rte_eth_dev *eth_dev) { struct qede_dev *qdev = eth_dev->data->dev_private; struct ecore_dev *edev = &qdev->edev; - PMD_INIT_FUNC_TRACE(edev); - - /* only uninitialize in the primary process */ - if (rte_eal_process_type() != RTE_PROC_PRIMARY) - return 0; - - /* safe to close dev here */ qede_dev_close(eth_dev); - - eth_dev->dev_ops = NULL; - eth_dev->rx_pkt_burst = NULL; - eth_dev->tx_pkt_burst = NULL; - return 0; } @@ -2715,13 +2892,5 @@ RTE_PMD_REGISTER_KMOD_DEP(net_qede, "* igb_uio | uio_pci_generic | vfio-pci"); RTE_PMD_REGISTER_PCI(net_qede_vf, rte_qedevf_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_qede_vf, pci_id_qedevf_map); RTE_PMD_REGISTER_KMOD_DEP(net_qede_vf, "* igb_uio | vfio-pci"); - -RTE_INIT(qede_init_log) -{ - qede_logtype_init = rte_log_register("pmd.net.qede.init"); - if (qede_logtype_init >= 0) - rte_log_set_level(qede_logtype_init, RTE_LOG_NOTICE); - qede_logtype_driver = rte_log_register("pmd.net.qede.driver"); - if (qede_logtype_driver >= 0) - rte_log_set_level(qede_logtype_driver, RTE_LOG_NOTICE); -} +RTE_LOG_REGISTER_SUFFIX(qede_logtype_init, init, NOTICE); +RTE_LOG_REGISTER_SUFFIX(qede_logtype_driver, driver, NOTICE);