|
@@ -176,6 +176,81 @@ static void enic_get_strings(struct net_device *netdev, u32 stringset,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void enic_get_ringparam(struct net_device *netdev,
|
|
|
|
+ struct ethtool_ringparam *ring)
|
|
|
|
+{
|
|
|
|
+ struct enic *enic = netdev_priv(netdev);
|
|
|
|
+ struct vnic_enet_config *c = &enic->config;
|
|
|
|
+
|
|
|
|
+ ring->rx_max_pending = ENIC_MAX_RQ_DESCS;
|
|
|
|
+ ring->rx_pending = c->rq_desc_count;
|
|
|
|
+ ring->tx_max_pending = ENIC_MAX_WQ_DESCS;
|
|
|
|
+ ring->tx_pending = c->wq_desc_count;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int enic_set_ringparam(struct net_device *netdev,
|
|
|
|
+ struct ethtool_ringparam *ring)
|
|
|
|
+{
|
|
|
|
+ struct enic *enic = netdev_priv(netdev);
|
|
|
|
+ struct vnic_enet_config *c = &enic->config;
|
|
|
|
+ int running = netif_running(netdev);
|
|
|
|
+ unsigned int rx_pending;
|
|
|
|
+ unsigned int tx_pending;
|
|
|
|
+ int err = 0;
|
|
|
|
+
|
|
|
|
+ if (ring->rx_mini_max_pending || ring->rx_mini_pending) {
|
|
|
|
+ netdev_info(netdev,
|
|
|
|
+ "modifying mini ring params is not supported");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (ring->rx_jumbo_max_pending || ring->rx_jumbo_pending) {
|
|
|
|
+ netdev_info(netdev,
|
|
|
|
+ "modifying jumbo ring params is not supported");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ rx_pending = c->rq_desc_count;
|
|
|
|
+ tx_pending = c->wq_desc_count;
|
|
|
|
+ if (ring->rx_pending > ENIC_MAX_RQ_DESCS ||
|
|
|
|
+ ring->rx_pending < ENIC_MIN_RQ_DESCS) {
|
|
|
|
+ netdev_info(netdev, "rx pending (%u) not in range [%u,%u]",
|
|
|
|
+ ring->rx_pending, ENIC_MIN_RQ_DESCS,
|
|
|
|
+ ENIC_MAX_RQ_DESCS);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (ring->tx_pending > ENIC_MAX_WQ_DESCS ||
|
|
|
|
+ ring->tx_pending < ENIC_MIN_WQ_DESCS) {
|
|
|
|
+ netdev_info(netdev, "tx pending (%u) not in range [%u,%u]",
|
|
|
|
+ ring->tx_pending, ENIC_MIN_WQ_DESCS,
|
|
|
|
+ ENIC_MAX_WQ_DESCS);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+ if (running)
|
|
|
|
+ dev_close(netdev);
|
|
|
|
+ c->rq_desc_count =
|
|
|
|
+ ring->rx_pending & 0xffffffe0; /* must be aligned to groups of 32 */
|
|
|
|
+ c->wq_desc_count =
|
|
|
|
+ ring->tx_pending & 0xffffffe0; /* must be aligned to groups of 32 */
|
|
|
|
+ enic_free_vnic_resources(enic);
|
|
|
|
+ err = enic_alloc_vnic_resources(enic);
|
|
|
|
+ if (err) {
|
|
|
|
+ netdev_err(netdev,
|
|
|
|
+ "Failed to alloc vNIC resources, aborting\n");
|
|
|
|
+ enic_free_vnic_resources(enic);
|
|
|
|
+ goto err_out;
|
|
|
|
+ }
|
|
|
|
+ enic_init_vnic_resources(enic);
|
|
|
|
+ if (running) {
|
|
|
|
+ err = dev_open(netdev);
|
|
|
|
+ if (err)
|
|
|
|
+ goto err_out;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+err_out:
|
|
|
|
+ c->rq_desc_count = rx_pending;
|
|
|
|
+ c->wq_desc_count = tx_pending;
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
static int enic_get_sset_count(struct net_device *netdev, int sset)
|
|
static int enic_get_sset_count(struct net_device *netdev, int sset)
|
|
{
|
|
{
|
|
switch (sset) {
|
|
switch (sset) {
|
|
@@ -509,6 +584,8 @@ static const struct ethtool_ops enic_ethtool_ops = {
|
|
.set_msglevel = enic_set_msglevel,
|
|
.set_msglevel = enic_set_msglevel,
|
|
.get_link = ethtool_op_get_link,
|
|
.get_link = ethtool_op_get_link,
|
|
.get_strings = enic_get_strings,
|
|
.get_strings = enic_get_strings,
|
|
|
|
+ .get_ringparam = enic_get_ringparam,
|
|
|
|
+ .set_ringparam = enic_set_ringparam,
|
|
.get_sset_count = enic_get_sset_count,
|
|
.get_sset_count = enic_get_sset_count,
|
|
.get_ethtool_stats = enic_get_ethtool_stats,
|
|
.get_ethtool_stats = enic_get_ethtool_stats,
|
|
.get_coalesce = enic_get_coalesce,
|
|
.get_coalesce = enic_get_coalesce,
|