static int enic_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) { struct enic *enic = netdev_priv(netdev); u32 tx_coalesce_usecs; u32 rx_coalesce_usecs; u32 rx_coalesce_usecs_low; u32 rx_coalesce_usecs_high; u32 coalesce_usecs_max; unsigned int i, intr; int ret; struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting; ret = enic_coalesce_valid(enic, ecmd); if (ret) return ret; coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev); tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs, coalesce_usecs_max); rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs, coalesce_usecs_max); rx_coalesce_usecs_low = min_t(u32, ecmd->rx_coalesce_usecs_low, coalesce_usecs_max); rx_coalesce_usecs_high = min_t(u32, ecmd->rx_coalesce_usecs_high, coalesce_usecs_max); if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) { for (i = 0; i < enic->wq_count; i++) { intr = enic_msix_wq_intr(enic, i); vnic_intr_coalescing_timer_set(&enic->intr[intr], tx_coalesce_usecs); } enic->tx_coalesce_usecs = tx_coalesce_usecs; } rxcoal->use_adaptive_rx_coalesce = !!ecmd->use_adaptive_rx_coalesce; if (!rxcoal->use_adaptive_rx_coalesce) enic_intr_coal_set_rx(enic, rx_coalesce_usecs); if (ecmd->rx_coalesce_usecs_high) { rxcoal->range_end = rx_coalesce_usecs_high; rxcoal->small_pkt_range_start = rx_coalesce_usecs_low; rxcoal->large_pkt_range_start = rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF; } enic->rx_coalesce_usecs = rx_coalesce_usecs; return 0; }
static int enic_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecmd) { struct enic *enic = netdev_priv(netdev); u32 tx_coalesce_usecs; u32 rx_coalesce_usecs; u32 rx_coalesce_usecs_low; u32 rx_coalesce_usecs_high; u32 coalesce_usecs_max; unsigned int i, intr; struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting; coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev); tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs, coalesce_usecs_max); rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs, coalesce_usecs_max); rx_coalesce_usecs_low = min_t(u32, ecmd->rx_coalesce_usecs_low, coalesce_usecs_max); rx_coalesce_usecs_high = min_t(u32, ecmd->rx_coalesce_usecs_high, coalesce_usecs_max); switch (vnic_dev_get_intr_mode(enic->vdev)) { case VNIC_DEV_INTR_MODE_INTX: if (tx_coalesce_usecs != rx_coalesce_usecs) return -EINVAL; if (ecmd->use_adaptive_rx_coalesce || ecmd->rx_coalesce_usecs_low || ecmd->rx_coalesce_usecs_high) return -EINVAL; intr = enic_legacy_io_intr(); vnic_intr_coalescing_timer_set(&enic->intr[intr], tx_coalesce_usecs); break; case VNIC_DEV_INTR_MODE_MSI: if (tx_coalesce_usecs != rx_coalesce_usecs) return -EINVAL; if (ecmd->use_adaptive_rx_coalesce || ecmd->rx_coalesce_usecs_low || ecmd->rx_coalesce_usecs_high) return -EINVAL; vnic_intr_coalescing_timer_set(&enic->intr[0], tx_coalesce_usecs); break; case VNIC_DEV_INTR_MODE_MSIX: if (ecmd->rx_coalesce_usecs_high && (rx_coalesce_usecs_high < rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF)) return -EINVAL; for (i = 0; i < enic->wq_count; i++) { intr = enic_msix_wq_intr(enic, i); vnic_intr_coalescing_timer_set(&enic->intr[intr], tx_coalesce_usecs); } rxcoal->use_adaptive_rx_coalesce = !!ecmd->use_adaptive_rx_coalesce; if (!rxcoal->use_adaptive_rx_coalesce) enic_intr_coal_set_rx(enic, rx_coalesce_usecs); if (ecmd->rx_coalesce_usecs_high) { rxcoal->range_end = rx_coalesce_usecs_high; rxcoal->small_pkt_range_start = rx_coalesce_usecs_low; rxcoal->large_pkt_range_start = rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF; } break; default: break; } enic->tx_coalesce_usecs = tx_coalesce_usecs; enic->rx_coalesce_usecs = rx_coalesce_usecs; return 0; }