diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index 1dacfe568..9d28dd212 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -478,6 +478,9 @@ struct mqnic_priv { u32 txq_count; u32 rxq_count; + u32 tx_ring_size; + u32 rx_ring_size; + struct rw_semaphore txq_table_sem; struct radix_tree_root txq_table; diff --git a/modules/mqnic/mqnic_ethtool.c b/modules/mqnic/mqnic_ethtool.c index 589f60017..543f788bb 100644 --- a/modules/mqnic/mqnic_ethtool.c +++ b/modules/mqnic/mqnic_ethtool.c @@ -58,6 +58,94 @@ static void mqnic_get_drvinfo(struct net_device *ndev, strscpy(drvinfo->bus_info, dev_name(mdev->dev), sizeof(drvinfo->bus_info)); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) +static void mqnic_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param, + struct kernel_ethtool_ringparam *kernel_param, + struct netlink_ext_ack *ext_ack) +#else +static void mqnic_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param) +#endif +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + memset(param, 0, sizeof(*param)); + + param->rx_max_pending = MQNIC_MAX_RX_RING_SZ; + param->tx_max_pending = MQNIC_MAX_TX_RING_SZ; + + param->rx_pending = priv->rx_ring_size; + param->tx_pending = priv->tx_ring_size; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) + memset(kernel_param, 0, sizeof(*kernel_param)); + + kernel_param->cqe_size = MQNIC_CPL_SIZE; +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) +static int mqnic_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param, + struct kernel_ethtool_ringparam *kernel_param, + struct netlink_ext_ack *ext_ack) +#else +static int mqnic_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param) +#endif +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 tx_ring_size, rx_ring_size; + int port_up = priv->port_up; + int ret = 0; + + if (param->rx_mini_pending || param->rx_jumbo_pending) + return -EINVAL; + + if (param->rx_pending < MQNIC_MIN_RX_RING_SZ) + return -EINVAL; + + if (param->rx_pending > MQNIC_MAX_RX_RING_SZ) + return -EINVAL; + + if (param->tx_pending < MQNIC_MIN_TX_RING_SZ) + return -EINVAL; + + if (param->tx_pending > MQNIC_MAX_TX_RING_SZ) + return -EINVAL; + + rx_ring_size = roundup_pow_of_two(param->rx_pending); + tx_ring_size = roundup_pow_of_two(param->tx_pending); + + if (rx_ring_size == priv->rx_ring_size && + tx_ring_size == priv->tx_ring_size) + return 0; + + dev_info(priv->dev, "New TX ring size: %d", tx_ring_size); + dev_info(priv->dev, "New RX ring size: %d", rx_ring_size); + + mutex_lock(&priv->mdev->state_lock); + + if (port_up) + mqnic_stop_port(ndev); + + priv->tx_ring_size = tx_ring_size; + priv->rx_ring_size = rx_ring_size; + + if (port_up) { + ret = mqnic_start_port(ndev); + + if (ret) + dev_err(priv->dev, "%s: Failed to start port on interface %d netdev %d: %d", + __func__, priv->interface->index, priv->index, ret); + } + + mutex_unlock(&priv->mdev->state_lock); + + return ret; +} + static int mqnic_get_ts_info(struct net_device *ndev, struct ethtool_ts_info *info) { @@ -343,6 +431,8 @@ static int mqnic_get_module_eeprom_by_page(struct net_device *ndev, const struct ethtool_ops mqnic_ethtool_ops = { .get_drvinfo = mqnic_get_drvinfo, .get_link = ethtool_op_get_link, + .get_ringparam = mqnic_get_ringparam, + .set_ringparam = mqnic_set_ringparam, .get_ts_info = mqnic_get_ts_info, .get_module_info = mqnic_get_module_info, .get_module_eeprom = mqnic_get_module_eeprom, diff --git a/modules/mqnic/mqnic_hw.h b/modules/mqnic/mqnic_hw.h index 4b982166e..d9e0a2fe1 100644 --- a/modules/mqnic/mqnic_hw.h +++ b/modules/mqnic/mqnic_hw.h @@ -52,6 +52,11 @@ #define MQNIC_MAX_RXQ 8192 #define MQNIC_MAX_RX_CQ MQNIC_MAX_RXQ +#define MQNIC_MIN_TX_RING_SZ (4096/16) +#define MQNIC_MAX_TX_RING_SZ 32768 +#define MQNIC_MIN_RX_RING_SZ (4096/16) +#define MQNIC_MAX_RX_RING_SZ 32768 + #define MQNIC_MAX_I2C_ADAPTERS 4 #define MQNIC_BOARD_ID_NETFPGA_SUME 0x10ee7028 diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index a83bf3577..e2a6183e3 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -64,7 +64,7 @@ int mqnic_start_port(struct net_device *ndev) goto fail; } - ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], mqnic_num_rxq_entries, 0); + ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->rx_ring_size, 0); if (ret) { mqnic_destroy_cq(cq); goto fail; @@ -93,7 +93,7 @@ int mqnic_start_port(struct net_device *ndev) else q->page_order = ilog2((ndev->mtu + ETH_HLEN + PAGE_SIZE - 1) / PAGE_SIZE - 1) + 1; - ret = mqnic_open_rx_ring(q, priv, cq, mqnic_num_rxq_entries, 1); + ret = mqnic_open_rx_ring(q, priv, cq, priv->rx_ring_size, 1); if (ret) { mqnic_destroy_rx_ring(q); mqnic_destroy_cq(cq); @@ -119,7 +119,7 @@ int mqnic_start_port(struct net_device *ndev) goto fail; } - ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], mqnic_num_txq_entries, 1); + ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->tx_ring_size, 1); if (ret) { mqnic_destroy_cq(cq); goto fail; @@ -144,7 +144,7 @@ int mqnic_start_port(struct net_device *ndev) q->tx_queue = netdev_get_tx_queue(ndev, k); - ret = mqnic_open_tx_ring(q, priv, cq, mqnic_num_txq_entries, desc_block_size); + ret = mqnic_open_tx_ring(q, priv, cq, priv->tx_ring_size, desc_block_size); if (ret) { mqnic_destroy_tx_ring(q); mqnic_destroy_cq(cq); @@ -566,6 +566,9 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, in priv->txq_count = mqnic_res_get_count(interface->txq_res); priv->rxq_count = mqnic_res_get_count(interface->rxq_res); + priv->tx_ring_size = mqnic_num_txq_entries; + priv->rx_ring_size = mqnic_num_rxq_entries; + init_rwsem(&priv->txq_table_sem); INIT_RADIX_TREE(&priv->txq_table, GFP_KERNEL);