aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/emulex/benet/be_main.c
diff options
context:
space:
mode:
authorSathya Perla <sathya.perla@emulex.com>2013-10-01 06:30:00 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-01 12:45:52 -0400
commit2632bafd74ae7d058ae52be80e6393139fd29f23 (patch)
treea1119a741b44afc7e68ab02b320a306c2238df30 /drivers/net/ethernet/emulex/benet/be_main.c
parent0599863d35410ea65ceadcca87497985b371039a (diff)
be2net: fix adaptive interrupt coalescing
The current EQ delay calculation for AIC is based only on RX packet rate. This fails to be effective when there's only TX and no RX. This patch inclues: - Calculating EQ-delay based on both RX and TX pps. - Modifying EQ-delay of all EQs via one cmd, instead of issuing a separate cmd for each EQ. - A new structure to store interrupt coalescing parameters, in a separate cache-line from the EQ-obj. Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c110
1 files changed, 68 insertions, 42 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 961e9f0500c5..6691d75b6cca 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1261,53 +1261,79 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
1261 return status; 1261 return status;
1262} 1262}
1263 1263
1264static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) 1264static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
1265 ulong now)
1265{ 1266{
1266 struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); 1267 aic->rx_pkts_prev = rx_pkts;
1267 ulong now = jiffies; 1268 aic->tx_reqs_prev = tx_pkts;
1268 ulong delta = now - stats->rx_jiffies; 1269 aic->jiffies = now;
1269 u64 pkts; 1270}
1270 unsigned int start, eqd;
1271 1271
1272 if (!eqo->enable_aic) { 1272static void be_eqd_update(struct be_adapter *adapter)
1273 eqd = eqo->eqd; 1273{
1274 goto modify_eqd; 1274 struct be_set_eqd set_eqd[MAX_EVT_QS];
1275 } 1275 int eqd, i, num = 0, start;
1276 struct be_aic_obj *aic;
1277 struct be_eq_obj *eqo;
1278 struct be_rx_obj *rxo;
1279 struct be_tx_obj *txo;
1280 u64 rx_pkts, tx_pkts;
1281 ulong now;
1282 u32 pps, delta;
1276 1283
1277 if (eqo->idx >= adapter->num_rx_qs) 1284 for_all_evt_queues(adapter, eqo, i) {
1278 return; 1285 aic = &adapter->aic_obj[eqo->idx];
1286 if (!aic->enable) {
1287 if (aic->jiffies)
1288 aic->jiffies = 0;
1289 eqd = aic->et_eqd;
1290 goto modify_eqd;
1291 }
1279 1292
1280 stats = rx_stats(&adapter->rx_obj[eqo->idx]); 1293 rxo = &adapter->rx_obj[eqo->idx];
1294 do {
1295 start = u64_stats_fetch_begin_bh(&rxo->stats.sync);
1296 rx_pkts = rxo->stats.rx_pkts;
1297 } while (u64_stats_fetch_retry_bh(&rxo->stats.sync, start));
1281 1298
1282 /* Wrapped around */ 1299 txo = &adapter->tx_obj[eqo->idx];
1283 if (time_before(now, stats->rx_jiffies)) { 1300 do {
1284 stats->rx_jiffies = now; 1301 start = u64_stats_fetch_begin_bh(&txo->stats.sync);
1285 return; 1302 tx_pkts = txo->stats.tx_reqs;
1286 } 1303 } while (u64_stats_fetch_retry_bh(&txo->stats.sync, start));
1287 1304
1288 /* Update once a second */
1289 if (delta < HZ)
1290 return;
1291 1305
1292 do { 1306 /* Skip, if wrapped around or first calculation */
1293 start = u64_stats_fetch_begin_bh(&stats->sync); 1307 now = jiffies;
1294 pkts = stats->rx_pkts; 1308 if (!aic->jiffies || time_before(now, aic->jiffies) ||
1295 } while (u64_stats_fetch_retry_bh(&stats->sync, start)); 1309 rx_pkts < aic->rx_pkts_prev ||
1296 1310 tx_pkts < aic->tx_reqs_prev) {
1297 stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ); 1311 be_aic_update(aic, rx_pkts, tx_pkts, now);
1298 stats->rx_pkts_prev = pkts; 1312 continue;
1299 stats->rx_jiffies = now; 1313 }
1300 eqd = (stats->rx_pps / 110000) << 3; 1314
1301 eqd = min(eqd, eqo->max_eqd); 1315 delta = jiffies_to_msecs(now - aic->jiffies);
1302 eqd = max(eqd, eqo->min_eqd); 1316 pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) +
1303 if (eqd < 10) 1317 (((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta);
1304 eqd = 0; 1318 eqd = (pps / 15000) << 2;
1305 1319
1320 if (eqd < 8)
1321 eqd = 0;
1322 eqd = min_t(u32, eqd, aic->max_eqd);
1323 eqd = max_t(u32, eqd, aic->min_eqd);
1324
1325 be_aic_update(aic, rx_pkts, tx_pkts, now);
1306modify_eqd: 1326modify_eqd:
1307 if (eqd != eqo->cur_eqd) { 1327 if (eqd != aic->prev_eqd) {
1308 be_cmd_modify_eqd(adapter, eqo->q.id, eqd); 1328 set_eqd[num].delay_multiplier = (eqd * 65)/100;
1309 eqo->cur_eqd = eqd; 1329 set_eqd[num].eq_id = eqo->q.id;
1330 aic->prev_eqd = eqd;
1331 num++;
1332 }
1310 } 1333 }
1334
1335 if (num)
1336 be_cmd_modify_eqd(adapter, set_eqd, num);
1311} 1337}
1312 1338
1313static void be_rx_stats_update(struct be_rx_obj *rxo, 1339static void be_rx_stats_update(struct be_rx_obj *rxo,
@@ -1924,6 +1950,7 @@ static int be_evt_queues_create(struct be_adapter *adapter)
1924{ 1950{
1925 struct be_queue_info *eq; 1951 struct be_queue_info *eq;
1926 struct be_eq_obj *eqo; 1952 struct be_eq_obj *eqo;
1953 struct be_aic_obj *aic;
1927 int i, rc; 1954 int i, rc;
1928 1955
1929 adapter->num_evt_qs = min_t(u16, num_irqs(adapter), 1956 adapter->num_evt_qs = min_t(u16, num_irqs(adapter),
@@ -1932,11 +1959,12 @@ static int be_evt_queues_create(struct be_adapter *adapter)
1932 for_all_evt_queues(adapter, eqo, i) { 1959 for_all_evt_queues(adapter, eqo, i) {
1933 netif_napi_add(adapter->netdev, &eqo->napi, be_poll, 1960 netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
1934 BE_NAPI_WEIGHT); 1961 BE_NAPI_WEIGHT);
1962 aic = &adapter->aic_obj[i];
1935 eqo->adapter = adapter; 1963 eqo->adapter = adapter;
1936 eqo->tx_budget = BE_TX_BUDGET; 1964 eqo->tx_budget = BE_TX_BUDGET;
1937 eqo->idx = i; 1965 eqo->idx = i;
1938 eqo->max_eqd = BE_MAX_EQD; 1966 aic->max_eqd = BE_MAX_EQD;
1939 eqo->enable_aic = true; 1967 aic->enable = true;
1940 1968
1941 eq = &eqo->q; 1969 eq = &eqo->q;
1942 rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, 1970 rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
@@ -4240,7 +4268,6 @@ static void be_worker(struct work_struct *work)
4240 struct be_adapter *adapter = 4268 struct be_adapter *adapter =
4241 container_of(work, struct be_adapter, work.work); 4269 container_of(work, struct be_adapter, work.work);
4242 struct be_rx_obj *rxo; 4270 struct be_rx_obj *rxo;
4243 struct be_eq_obj *eqo;
4244 int i; 4271 int i;
4245 4272
4246 /* when interrupts are not yet enabled, just reap any pending 4273 /* when interrupts are not yet enabled, just reap any pending
@@ -4271,8 +4298,7 @@ static void be_worker(struct work_struct *work)
4271 } 4298 }
4272 } 4299 }
4273 4300
4274 for_all_evt_queues(adapter, eqo, i) 4301 be_eqd_update(adapter);
4275 be_eqd_update(adapter, eqo);
4276 4302
4277reschedule: 4303reschedule:
4278 adapter->work_counter++; 4304 adapter->work_counter++;