|
@@ -1149,6 +1149,64 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void enic_set_int_moderation(struct enic *enic, struct vnic_rq *rq)
|
|
|
+{
|
|
|
+ unsigned int intr = enic_msix_rq_intr(enic, rq->index);
|
|
|
+ struct vnic_cq *cq = &enic->cq[enic_cq_rq(enic, rq->index)];
|
|
|
+ u32 timer = cq->tobe_rx_coal_timeval;
|
|
|
+
|
|
|
+ if (cq->tobe_rx_coal_timeval != cq->cur_rx_coal_timeval) {
|
|
|
+ vnic_intr_coalescing_timer_set(&enic->intr[intr], timer);
|
|
|
+ cq->cur_rx_coal_timeval = cq->tobe_rx_coal_timeval;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void enic_calc_int_moderation(struct enic *enic, struct vnic_rq *rq)
|
|
|
+{
|
|
|
+ struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
|
|
|
+ struct vnic_cq *cq = &enic->cq[enic_cq_rq(enic, rq->index)];
|
|
|
+ struct vnic_rx_bytes_counter *pkt_size_counter = &cq->pkt_size_counter;
|
|
|
+ int index;
|
|
|
+ u32 timer;
|
|
|
+ u32 range_start;
|
|
|
+ u32 traffic;
|
|
|
+ u64 delta;
|
|
|
+ ktime_t now = ktime_get();
|
|
|
+
|
|
|
+ delta = ktime_us_delta(now, cq->prev_ts);
|
|
|
+ if (delta < ENIC_AIC_TS_BREAK)
|
|
|
+ return;
|
|
|
+ cq->prev_ts = now;
|
|
|
+
|
|
|
+ traffic = pkt_size_counter->large_pkt_bytes_cnt +
|
|
|
+ pkt_size_counter->small_pkt_bytes_cnt;
|
|
|
+ /* The table takes Mbps
|
|
|
+ * traffic *= 8 => bits
|
|
|
+ * traffic *= (10^6 / delta) => bps
|
|
|
+ * traffic /= 10^6 => Mbps
|
|
|
+ *
|
|
|
+ * Combining, traffic *= (8 / delta)
|
|
|
+ */
|
|
|
+
|
|
|
+ traffic <<= 3;
|
|
|
+ traffic = delta > UINT_MAX ? 0 : traffic / (u32)delta;
|
|
|
+
|
|
|
+ for (index = 0; index < ENIC_MAX_COALESCE_TIMERS; index++)
|
|
|
+ if (traffic < mod_table[index].rx_rate)
|
|
|
+ break;
|
|
|
+ range_start = (pkt_size_counter->small_pkt_bytes_cnt >
|
|
|
+ pkt_size_counter->large_pkt_bytes_cnt << 1) ?
|
|
|
+ rx_coal->small_pkt_range_start :
|
|
|
+ rx_coal->large_pkt_range_start;
|
|
|
+ timer = range_start + ((rx_coal->range_end - range_start) *
|
|
|
+ mod_table[index].range_percent / 100);
|
|
|
+ /* Damping */
|
|
|
+ cq->tobe_rx_coal_timeval = (timer + cq->tobe_rx_coal_timeval) >> 1;
|
|
|
+
|
|
|
+ pkt_size_counter->large_pkt_bytes_cnt = 0;
|
|
|
+ pkt_size_counter->small_pkt_bytes_cnt = 0;
|
|
|
+}
|
|
|
+
|
|
|
static int enic_poll(struct napi_struct *napi, int budget)
|
|
|
{
|
|
|
struct net_device *netdev = napi->dev;
|
|
@@ -1199,6 +1257,11 @@ static int enic_poll(struct napi_struct *napi, int budget)
|
|
|
|
|
|
if (err)
|
|
|
rq_work_done = rq_work_to_do;
|
|
|
+ if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
|
|
|
+ /* Call the function which refreshes the intr coalescing timer
|
|
|
+ * value based on the traffic.
|
|
|
+ */
|
|
|
+ enic_calc_int_moderation(enic, &enic->rq[0]);
|
|
|
|
|
|
if (rq_work_done < rq_work_to_do) {
|
|
|
|
|
@@ -1207,70 +1270,14 @@ static int enic_poll(struct napi_struct *napi, int budget)
|
|
|
*/
|
|
|
|
|
|
napi_complete(napi);
|
|
|
+ if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
|
|
|
+ enic_set_int_moderation(enic, &enic->rq[0]);
|
|
|
vnic_intr_unmask(&enic->intr[intr]);
|
|
|
}
|
|
|
|
|
|
return rq_work_done;
|
|
|
}
|
|
|
|
|
|
-static void enic_set_int_moderation(struct enic *enic, struct vnic_rq *rq)
|
|
|
-{
|
|
|
- unsigned int intr = enic_msix_rq_intr(enic, rq->index);
|
|
|
- struct vnic_cq *cq = &enic->cq[enic_cq_rq(enic, rq->index)];
|
|
|
- u32 timer = cq->tobe_rx_coal_timeval;
|
|
|
-
|
|
|
- if (cq->tobe_rx_coal_timeval != cq->cur_rx_coal_timeval) {
|
|
|
- vnic_intr_coalescing_timer_set(&enic->intr[intr], timer);
|
|
|
- cq->cur_rx_coal_timeval = cq->tobe_rx_coal_timeval;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void enic_calc_int_moderation(struct enic *enic, struct vnic_rq *rq)
|
|
|
-{
|
|
|
- struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
|
|
|
- struct vnic_cq *cq = &enic->cq[enic_cq_rq(enic, rq->index)];
|
|
|
- struct vnic_rx_bytes_counter *pkt_size_counter = &cq->pkt_size_counter;
|
|
|
- int index;
|
|
|
- u32 timer;
|
|
|
- u32 range_start;
|
|
|
- u32 traffic;
|
|
|
- u64 delta;
|
|
|
- ktime_t now = ktime_get();
|
|
|
-
|
|
|
- delta = ktime_us_delta(now, cq->prev_ts);
|
|
|
- if (delta < ENIC_AIC_TS_BREAK)
|
|
|
- return;
|
|
|
- cq->prev_ts = now;
|
|
|
-
|
|
|
- traffic = pkt_size_counter->large_pkt_bytes_cnt +
|
|
|
- pkt_size_counter->small_pkt_bytes_cnt;
|
|
|
- /* The table takes Mbps
|
|
|
- * traffic *= 8 => bits
|
|
|
- * traffic *= (10^6 / delta) => bps
|
|
|
- * traffic /= 10^6 => Mbps
|
|
|
- *
|
|
|
- * Combining, traffic *= (8 / delta)
|
|
|
- */
|
|
|
-
|
|
|
- traffic <<= 3;
|
|
|
- traffic = delta > UINT_MAX ? 0 : traffic / (u32)delta;
|
|
|
-
|
|
|
- for (index = 0; index < ENIC_MAX_COALESCE_TIMERS; index++)
|
|
|
- if (traffic < mod_table[index].rx_rate)
|
|
|
- break;
|
|
|
- range_start = (pkt_size_counter->small_pkt_bytes_cnt >
|
|
|
- pkt_size_counter->large_pkt_bytes_cnt << 1) ?
|
|
|
- rx_coal->small_pkt_range_start :
|
|
|
- rx_coal->large_pkt_range_start;
|
|
|
- timer = range_start + ((rx_coal->range_end - range_start) *
|
|
|
- mod_table[index].range_percent / 100);
|
|
|
- /* Damping */
|
|
|
- cq->tobe_rx_coal_timeval = (timer + cq->tobe_rx_coal_timeval) >> 1;
|
|
|
-
|
|
|
- pkt_size_counter->large_pkt_bytes_cnt = 0;
|
|
|
- pkt_size_counter->small_pkt_bytes_cnt = 0;
|
|
|
-}
|
|
|
-
|
|
|
#ifdef CONFIG_RFS_ACCEL
|
|
|
static void enic_free_rx_cpu_rmap(struct enic *enic)
|
|
|
{
|
|
@@ -1407,10 +1414,8 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
|
|
|
if (err)
|
|
|
work_done = work_to_do;
|
|
|
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
|
|
|
- /* Call the function which refreshes
|
|
|
- * the intr coalescing timer value based on
|
|
|
- * the traffic. This is supported only in
|
|
|
- * the case of MSI-x mode
|
|
|
+ /* Call the function which refreshes the intr coalescing timer
|
|
|
+ * value based on the traffic.
|
|
|
*/
|
|
|
enic_calc_int_moderation(enic, &enic->rq[rq]);
|
|
|
|
|
@@ -1569,12 +1574,6 @@ static void enic_set_rx_coal_setting(struct enic *enic)
|
|
|
int index = -1;
|
|
|
struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
|
|
|
|
|
|
- /* If intr mode is not MSIX, do not do adaptive coalescing */
|
|
|
- if (VNIC_DEV_INTR_MODE_MSIX != vnic_dev_get_intr_mode(enic->vdev)) {
|
|
|
- netdev_info(enic->netdev, "INTR mode is not MSIX, Not initializing adaptive coalescing");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
/* 1. Read the link speed from fw
|
|
|
* 2. Pick the default range for the speed
|
|
|
* 3. Update it in enic->rx_coalesce_setting
|