|
@@ -1261,53 +1261,79 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo)
|
|
|
+static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
|
|
|
+ ulong now)
|
|
|
{
|
|
|
- struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]);
|
|
|
- ulong now = jiffies;
|
|
|
- ulong delta = now - stats->rx_jiffies;
|
|
|
- u64 pkts;
|
|
|
- unsigned int start, eqd;
|
|
|
+ aic->rx_pkts_prev = rx_pkts;
|
|
|
+ aic->tx_reqs_prev = tx_pkts;
|
|
|
+ aic->jiffies = now;
|
|
|
+}
|
|
|
|
|
|
- if (!eqo->enable_aic) {
|
|
|
- eqd = eqo->eqd;
|
|
|
- goto modify_eqd;
|
|
|
- }
|
|
|
+static void be_eqd_update(struct be_adapter *adapter)
|
|
|
+{
|
|
|
+ struct be_set_eqd set_eqd[MAX_EVT_QS];
|
|
|
+ int eqd, i, num = 0, start;
|
|
|
+ struct be_aic_obj *aic;
|
|
|
+ struct be_eq_obj *eqo;
|
|
|
+ struct be_rx_obj *rxo;
|
|
|
+ struct be_tx_obj *txo;
|
|
|
+ u64 rx_pkts, tx_pkts;
|
|
|
+ ulong now;
|
|
|
+ u32 pps, delta;
|
|
|
|
|
|
- if (eqo->idx >= adapter->num_rx_qs)
|
|
|
- return;
|
|
|
+ for_all_evt_queues(adapter, eqo, i) {
|
|
|
+ aic = &adapter->aic_obj[eqo->idx];
|
|
|
+ if (!aic->enable) {
|
|
|
+ if (aic->jiffies)
|
|
|
+ aic->jiffies = 0;
|
|
|
+ eqd = aic->et_eqd;
|
|
|
+ goto modify_eqd;
|
|
|
+ }
|
|
|
|
|
|
- stats = rx_stats(&adapter->rx_obj[eqo->idx]);
|
|
|
+ rxo = &adapter->rx_obj[eqo->idx];
|
|
|
+ do {
|
|
|
+ start = u64_stats_fetch_begin_bh(&rxo->stats.sync);
|
|
|
+ rx_pkts = rxo->stats.rx_pkts;
|
|
|
+ } while (u64_stats_fetch_retry_bh(&rxo->stats.sync, start));
|
|
|
|
|
|
- /* Wrapped around */
|
|
|
- if (time_before(now, stats->rx_jiffies)) {
|
|
|
- stats->rx_jiffies = now;
|
|
|
- return;
|
|
|
- }
|
|
|
+ txo = &adapter->tx_obj[eqo->idx];
|
|
|
+ do {
|
|
|
+ start = u64_stats_fetch_begin_bh(&txo->stats.sync);
|
|
|
+ tx_pkts = txo->stats.tx_reqs;
|
|
|
+ } while (u64_stats_fetch_retry_bh(&txo->stats.sync, start));
|
|
|
|
|
|
- /* Update once a second */
|
|
|
- if (delta < HZ)
|
|
|
- return;
|
|
|
|
|
|
- do {
|
|
|
- start = u64_stats_fetch_begin_bh(&stats->sync);
|
|
|
- pkts = stats->rx_pkts;
|
|
|
- } while (u64_stats_fetch_retry_bh(&stats->sync, start));
|
|
|
-
|
|
|
- stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ);
|
|
|
- stats->rx_pkts_prev = pkts;
|
|
|
- stats->rx_jiffies = now;
|
|
|
- eqd = (stats->rx_pps / 110000) << 3;
|
|
|
- eqd = min(eqd, eqo->max_eqd);
|
|
|
- eqd = max(eqd, eqo->min_eqd);
|
|
|
- if (eqd < 10)
|
|
|
- eqd = 0;
|
|
|
+ /* Skip, if wrapped around or first calculation */
|
|
|
+ now = jiffies;
|
|
|
+ if (!aic->jiffies || time_before(now, aic->jiffies) ||
|
|
|
+ rx_pkts < aic->rx_pkts_prev ||
|
|
|
+ tx_pkts < aic->tx_reqs_prev) {
|
|
|
+ be_aic_update(aic, rx_pkts, tx_pkts, now);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ delta = jiffies_to_msecs(now - aic->jiffies);
|
|
|
+ pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) +
|
|
|
+ (((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta);
|
|
|
+ eqd = (pps / 15000) << 2;
|
|
|
|
|
|
+ if (eqd < 8)
|
|
|
+ eqd = 0;
|
|
|
+ eqd = min_t(u32, eqd, aic->max_eqd);
|
|
|
+ eqd = max_t(u32, eqd, aic->min_eqd);
|
|
|
+
|
|
|
+ be_aic_update(aic, rx_pkts, tx_pkts, now);
|
|
|
modify_eqd:
|
|
|
- if (eqd != eqo->cur_eqd) {
|
|
|
- be_cmd_modify_eqd(adapter, eqo->q.id, eqd);
|
|
|
- eqo->cur_eqd = eqd;
|
|
|
+ if (eqd != aic->prev_eqd) {
|
|
|
+ set_eqd[num].delay_multiplier = (eqd * 65)/100;
|
|
|
+ set_eqd[num].eq_id = eqo->q.id;
|
|
|
+ aic->prev_eqd = eqd;
|
|
|
+ num++;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ if (num)
|
|
|
+ be_cmd_modify_eqd(adapter, set_eqd, num);
|
|
|
}
|
|
|
|
|
|
static void be_rx_stats_update(struct be_rx_obj *rxo,
|
|
@@ -1924,6 +1950,7 @@ static int be_evt_queues_create(struct be_adapter *adapter)
|
|
|
{
|
|
|
struct be_queue_info *eq;
|
|
|
struct be_eq_obj *eqo;
|
|
|
+ struct be_aic_obj *aic;
|
|
|
int i, rc;
|
|
|
|
|
|
adapter->num_evt_qs = min_t(u16, num_irqs(adapter),
|
|
@@ -1932,11 +1959,12 @@ static int be_evt_queues_create(struct be_adapter *adapter)
|
|
|
for_all_evt_queues(adapter, eqo, i) {
|
|
|
netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
|
|
|
BE_NAPI_WEIGHT);
|
|
|
+ aic = &adapter->aic_obj[i];
|
|
|
eqo->adapter = adapter;
|
|
|
eqo->tx_budget = BE_TX_BUDGET;
|
|
|
eqo->idx = i;
|
|
|
- eqo->max_eqd = BE_MAX_EQD;
|
|
|
- eqo->enable_aic = true;
|
|
|
+ aic->max_eqd = BE_MAX_EQD;
|
|
|
+ aic->enable = true;
|
|
|
|
|
|
eq = &eqo->q;
|
|
|
rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
|
|
@@ -4240,7 +4268,6 @@ static void be_worker(struct work_struct *work)
|
|
|
struct be_adapter *adapter =
|
|
|
container_of(work, struct be_adapter, work.work);
|
|
|
struct be_rx_obj *rxo;
|
|
|
- struct be_eq_obj *eqo;
|
|
|
int i;
|
|
|
|
|
|
/* when interrupts are not yet enabled, just reap any pending
|
|
@@ -4271,8 +4298,7 @@ static void be_worker(struct work_struct *work)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- for_all_evt_queues(adapter, eqo, i)
|
|
|
- be_eqd_update(adapter, eqo);
|
|
|
+ be_eqd_update(adapter);
|
|
|
|
|
|
reschedule:
|
|
|
adapter->work_counter++;
|