/* * This routine is used to set interrup coalescing delay */ static int be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) { struct be_adapter *adapter = netdev_priv(netdev); struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; u32 tx_max, tx_min, tx_cur; u32 rx_max, rx_min, rx_cur; int status = 0; if (coalesce->use_adaptive_tx_coalesce == 1) return -EINVAL; /* if AIC is being turned on now, start with an EQD of 0 */ if (rx_eq->enable_aic == 0 && coalesce->use_adaptive_rx_coalesce == 1) { rx_eq->cur_eqd = 0; } rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; rx_max = coalesce->rx_coalesce_usecs_high; rx_min = coalesce->rx_coalesce_usecs_low; rx_cur = coalesce->rx_coalesce_usecs; tx_max = coalesce->tx_coalesce_usecs_high; tx_min = coalesce->tx_coalesce_usecs_low; tx_cur = coalesce->tx_coalesce_usecs; if (tx_cur > BE_MAX_EQD) tx_cur = BE_MAX_EQD; if (tx_eq->cur_eqd != tx_cur) { status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur); if (!status) tx_eq->cur_eqd = tx_cur; } if (rx_eq->enable_aic) { if (rx_max > BE_MAX_EQD) rx_max = BE_MAX_EQD; if (rx_min > rx_max) rx_min = rx_max; rx_eq->max_eqd = rx_max; rx_eq->min_eqd = rx_min; if (rx_eq->cur_eqd > rx_max) rx_eq->cur_eqd = rx_max; if (rx_eq->cur_eqd < rx_min) rx_eq->cur_eqd = rx_min; } else { if (rx_cur > BE_MAX_EQD) rx_cur = BE_MAX_EQD; if (rx_eq->cur_eqd != rx_cur) { status = be_cmd_modify_eqd(adapter, rx_eq->q.id, rx_cur); if (!status) rx_eq->cur_eqd = rx_cur; } } return 0; }
/* Update the EQ delay n BE based on the RX frags consumed / sec */ static void be_rx_eqd_update(struct be_adapter *adapter) { u32 eqd; struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_drvr_stats *stats = &adapter->stats.drvr_stats; /* Update once a second */ if (((jiffies - stats->rx_fps_jiffies) < HZ) || rx_eq->enable_aic == 0) return; stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) / ((jiffies - stats->rx_fps_jiffies) / HZ); stats->rx_fps_jiffies = jiffies; stats->be_prev_rx_frags = stats->be_rx_frags; eqd = stats->be_rx_fps / 110000; eqd = eqd << 3; if (eqd > rx_eq->max_eqd) eqd = rx_eq->max_eqd; if (eqd < rx_eq->min_eqd) eqd = rx_eq->min_eqd; if (eqd < 10) eqd = 0; if (eqd != rx_eq->cur_eqd) be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd); rx_eq->cur_eqd = eqd; }
/* * This routine is used to set interrup coalescing delay */ static int be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) { struct be_adapter *adapter = netdev_priv(netdev); struct be_rx_obj *rxo; struct be_eq_obj *rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; u32 tx_max, tx_min, tx_cur; u32 rx_max, rx_min, rx_cur; int status = 0, i; if (coalesce->use_adaptive_tx_coalesce == 1) return -EINVAL; for_all_rx_queues(adapter, rxo, i) { rx_eq = &rxo->rx_eq; if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce) rx_eq->cur_eqd = 0; rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; rx_max = coalesce->rx_coalesce_usecs_high; rx_min = coalesce->rx_coalesce_usecs_low; rx_cur = coalesce->rx_coalesce_usecs; if (rx_eq->enable_aic) { if (rx_max > BE_MAX_EQD) rx_max = BE_MAX_EQD; if (rx_min > rx_max) rx_min = rx_max; rx_eq->max_eqd = rx_max; rx_eq->min_eqd = rx_min; if (rx_eq->cur_eqd > rx_max) rx_eq->cur_eqd = rx_max; if (rx_eq->cur_eqd < rx_min) rx_eq->cur_eqd = rx_min; } else { if (rx_cur > BE_MAX_EQD) rx_cur = BE_MAX_EQD; if (rx_eq->cur_eqd != rx_cur) { status = be_cmd_modify_eqd(adapter, rx_eq->q.id, rx_cur); if (!status) rx_eq->cur_eqd = rx_cur; } } }
/* Update the EQ delay n BE based on the RX frags consumed / sec */ static void be_rx_eqd_update(struct be_adapter *adapter) { struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_drvr_stats *stats = &adapter->stats.drvr_stats; ulong now = jiffies; u32 eqd; if (!rx_eq->enable_aic) return; /* Wrapped around */ if (time_before(now, stats->rx_fps_jiffies)) { stats->rx_fps_jiffies = now; return; } /* Update once a second */ if ((now - stats->rx_fps_jiffies) < HZ) return; stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) / ((now - stats->rx_fps_jiffies) / HZ); stats->rx_fps_jiffies = now; stats->be_prev_rx_frags = stats->be_rx_frags; eqd = stats->be_rx_fps / 110000; eqd = eqd << 3; if (eqd > rx_eq->max_eqd) eqd = rx_eq->max_eqd; if (eqd < rx_eq->min_eqd) eqd = rx_eq->min_eqd; if (eqd < 10) eqd = 0; if (eqd != rx_eq->cur_eqd) be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd); rx_eq->cur_eqd = eqd; }