diff options
Diffstat (limited to 'drivers/net/mlx4')
-rw-r--r-- | drivers/net/mlx4/en_main.c | 11 | ||||
-rw-r--r-- | drivers/net/mlx4/en_netdev.c | 8 | ||||
-rw-r--r-- | drivers/net/mlx4/en_params.c | 93 | ||||
-rw-r--r-- | drivers/net/mlx4/en_tx.c | 59 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4_en.h | 11 |
5 files changed, 108 insertions, 74 deletions
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index c1c05852a95e..eda72dd2120f 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -169,13 +169,10 @@ static void *mlx4_en_add(struct mlx4_dev *dev) mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { mlx4_info(mdev, "Using %d tx rings for port:%d\n", mdev->profile.prof[i].tx_ring_num, i); - if (!mdev->profile.prof[i].rx_ring_num) { - mdev->profile.prof[i].rx_ring_num = dev->caps.num_comp_vectors; - mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n", - mdev->profile.prof[i].rx_ring_num, i); - } else - mlx4_info(mdev, "Using %d rx rings for port:%d\n", - mdev->profile.prof[i].rx_ring_num, i); + mdev->profile.prof[i].rx_ring_num = + min_t(int, dev->caps.num_comp_vectors, MAX_RX_RINGS); + mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n", + mdev->profile.prof[i].rx_ring_num, i); } /* Create our own workqueue for reset/multicast tasks diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index ebada3c7aff2..15bb38d99304 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -552,7 +552,7 @@ static void mlx4_en_linkstate(struct work_struct *work) } -static int mlx4_en_start_port(struct net_device *dev) +int mlx4_en_start_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -707,7 +707,7 @@ cq_err: } -static void mlx4_en_stop_port(struct net_device *dev) +void mlx4_en_stop_port(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -826,7 +826,7 @@ static int mlx4_en_close(struct net_device *dev) return 0; } -static void mlx4_en_free_resources(struct mlx4_en_priv *priv) +void mlx4_en_free_resources(struct mlx4_en_priv *priv) { int i; @@ -845,7 +845,7 @@ static void mlx4_en_free_resources(struct mlx4_en_priv *priv) } } -static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) +int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) { struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_port_profile *prof = priv->prof; diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c index 047b37f5a747..c1bd040b9e05 100644 --- a/drivers/net/mlx4/en_params.c +++ b/drivers/net/mlx4/en_params.c @@ -65,15 +65,6 @@ MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]." MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]." " Per priority bit mask"); -MLX4_EN_PARM_INT(rx_ring_num1, 0, "Number or Rx rings for port 1 (0 = #cores)"); -MLX4_EN_PARM_INT(rx_ring_num2, 0, "Number or Rx rings for port 2 (0 = #cores)"); - -MLX4_EN_PARM_INT(tx_ring_size1, MLX4_EN_AUTO_CONF, "Tx ring size for port 1"); -MLX4_EN_PARM_INT(tx_ring_size2, MLX4_EN_AUTO_CONF, "Tx ring size for port 2"); -MLX4_EN_PARM_INT(rx_ring_size1, MLX4_EN_AUTO_CONF, "Rx ring size for port 1"); -MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2"); - - int mlx4_en_get_profile(struct mlx4_en_dev *mdev) { struct mlx4_en_profile *params = &mdev->profile; @@ -87,6 +78,8 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[i].rx_ppp = pfcrx; params->prof[i].tx_pause = 1; params->prof[i].tx_ppp = pfctx; + params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; + params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; } if (pfcrx || pfctx) { params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; @@ -95,32 +88,7 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[1].tx_ring_num = 1; params->prof[2].tx_ring_num = 1; } - params->prof[1].rx_ring_num = min_t(int, rx_ring_num1, MAX_RX_RINGS); - params->prof[2].rx_ring_num = min_t(int, rx_ring_num2, MAX_RX_RINGS); - - if (tx_ring_size1 == MLX4_EN_AUTO_CONF) - tx_ring_size1 = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[1].tx_ring_size = - (tx_ring_size1 < MLX4_EN_MIN_TX_SIZE) ? - MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size1); - - if (tx_ring_size2 == MLX4_EN_AUTO_CONF) - tx_ring_size2 = MLX4_EN_DEF_TX_RING_SIZE; - params->prof[2].tx_ring_size = - (tx_ring_size2 < MLX4_EN_MIN_TX_SIZE) ? - MLX4_EN_MIN_TX_SIZE : roundup_pow_of_two(tx_ring_size2); - - if (rx_ring_size1 == MLX4_EN_AUTO_CONF) - rx_ring_size1 = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[1].rx_ring_size = - (rx_ring_size1 < MLX4_EN_MIN_RX_SIZE) ? - MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size1); - - if (rx_ring_size2 == MLX4_EN_AUTO_CONF) - rx_ring_size2 = MLX4_EN_DEF_RX_RING_SIZE; - params->prof[2].rx_ring_size = - (rx_ring_size2 < MLX4_EN_MIN_RX_SIZE) ? - MLX4_EN_MIN_RX_SIZE : roundup_pow_of_two(rx_ring_size2); + return 0; } @@ -417,6 +385,56 @@ static void mlx4_en_get_pauseparam(struct net_device *dev, pause->rx_pause = priv->prof->rx_pause; } +static int mlx4_en_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + u32 rx_size, tx_size; + int port_up = 0; + int err = 0; + + if (param->rx_jumbo_pending || param->rx_mini_pending) + return -EINVAL; + + rx_size = roundup_pow_of_two(param->rx_pending); + rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE); + rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE); + tx_size = roundup_pow_of_two(param->tx_pending); + tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE); + tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE); + + if (rx_size == priv->prof->rx_ring_size && + tx_size == priv->prof->tx_ring_size) + return 0; + + mutex_lock(&mdev->state_lock); + if (priv->port_up) { + port_up = 1; + mlx4_en_stop_port(dev); + } + + mlx4_en_free_resources(priv); + + priv->prof->tx_ring_size = tx_size; + priv->prof->rx_ring_size = rx_size; + + err = mlx4_en_alloc_resources(priv); + if (err) { + mlx4_err(mdev, "Failed reallocating port resources\n"); + goto out; + } + if (port_up) { + err = mlx4_en_start_port(dev); + if (err) + mlx4_err(mdev, "Failed starting port\n"); + } + +out: + mutex_unlock(&mdev->state_lock); + return err; +} + static void mlx4_en_get_ringparam(struct net_device *dev, struct ethtool_ringparam *param) { @@ -424,8 +442,8 @@ static void mlx4_en_get_ringparam(struct net_device *dev, struct mlx4_en_dev *mdev = priv->mdev; memset(param, 0, sizeof(*param)); - param->rx_max_pending = mdev->dev->caps.max_rq_sg; - param->tx_max_pending = mdev->dev->caps.max_sq_sg; + param->rx_max_pending = MLX4_EN_MAX_RX_SIZE; + param->tx_max_pending = MLX4_EN_MAX_TX_SIZE; param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size; param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size; } @@ -456,6 +474,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_pauseparam = mlx4_en_get_pauseparam, .set_pauseparam = mlx4_en_set_pauseparam, .get_ringparam = mlx4_en_get_ringparam, + .set_ringparam = mlx4_en_set_ringparam, .get_flags = ethtool_op_get_flags, .set_flags = ethtool_op_set_flags, }; diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index ff4d75205c25..4afd5993e31c 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c @@ -203,19 +203,21 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, /* Optimize the common case when there are no wraparounds */ if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) { - if (tx_info->linear) { - pci_unmap_single(mdev->pdev, - (dma_addr_t) be64_to_cpu(data->addr), + if (!tx_info->inl) { + if (tx_info->linear) { + pci_unmap_single(mdev->pdev, + (dma_addr_t) be64_to_cpu(data->addr), be32_to_cpu(data->byte_count), PCI_DMA_TODEVICE); - ++data; - } + ++data; + } - for (i = 0; i < frags; i++) { - frag = &skb_shinfo(skb)->frags[i]; - pci_unmap_page(mdev->pdev, - (dma_addr_t) be64_to_cpu(data[i].addr), - frag->size, PCI_DMA_TODEVICE); + for (i = 0; i < frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + pci_unmap_page(mdev->pdev, + (dma_addr_t) be64_to_cpu(data[i].addr), + frag->size, PCI_DMA_TODEVICE); + } } /* Stamp the freed descriptor */ for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) { @@ -224,27 +226,29 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, } } else { - if ((void *) data >= end) { - data = (struct mlx4_wqe_data_seg *) - (ring->buf + ((void *) data - end)); - } + if (!tx_info->inl) { + if ((void *) data >= end) { + data = (struct mlx4_wqe_data_seg *) + (ring->buf + ((void *) data - end)); + } - if (tx_info->linear) { - pci_unmap_single(mdev->pdev, - (dma_addr_t) be64_to_cpu(data->addr), + if (tx_info->linear) { + pci_unmap_single(mdev->pdev, + (dma_addr_t) be64_to_cpu(data->addr), be32_to_cpu(data->byte_count), PCI_DMA_TODEVICE); - ++data; - } + ++data; + } - for (i = 0; i < frags; i++) { - /* Check for wraparound before unmapping */ - if ((void *) data >= end) - data = (struct mlx4_wqe_data_seg *) ring->buf; - frag = &skb_shinfo(skb)->frags[i]; - pci_unmap_page(mdev->pdev, + for (i = 0; i < frags; i++) { + /* Check for wraparound before unmapping */ + if ((void *) data >= end) + data = (struct mlx4_wqe_data_seg *) ring->buf; + frag = &skb_shinfo(skb)->frags[i]; + pci_unmap_page(mdev->pdev, (dma_addr_t) be64_to_cpu(data->addr), frag->size, PCI_DMA_TODEVICE); + } } /* Stamp the freed descriptor */ for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) { @@ -790,8 +794,11 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); data->byte_count = cpu_to_be32(skb_headlen(skb) - lso_header_size); } - } else + tx_info->inl = 0; + } else { build_inline_wqe(tx_desc, skb, real_size, &vlan_tag, tx_ind, fragptr); + tx_info->inl = 1; + } ring->prod += nr_txbb; diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index e78209768def..e9af32d41ca4 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -115,6 +115,10 @@ enum { }; #define MLX4_EN_MAX_RX_FRAGS 4 +/* Maximum ring sizes */ +#define MLX4_EN_MAX_TX_SIZE 8192 +#define MLX4_EN_MAX_RX_SIZE 8192 + /* Minimum ring size for our page-allocation sceme to work */ #define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES) #define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE) @@ -202,6 +206,7 @@ struct mlx4_en_tx_info { u32 nr_txbb; u8 linear; u8 data_offset; + u8 inl; }; @@ -489,6 +494,12 @@ void mlx4_en_destroy_netdev(struct net_device *dev); int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, struct mlx4_en_port_profile *prof); +int mlx4_en_start_port(struct net_device *dev); +void mlx4_en_stop_port(struct net_device *dev); + +void mlx4_en_free_resources(struct mlx4_en_priv *priv); +int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); + int mlx4_en_get_profile(struct mlx4_en_dev *mdev); int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, |