Skip to content

Commit b8c17f7

Browse files
Lin Yun Shengdavem330
authored andcommitted
net: hns: Add self-adaptive interrupt coalesce support in hns driver
When deal with low and high throughput, it is hard to achiece both high performance and low latency. In order to achiece that, this patch calculates the rx rate, and adjust the interrupt coalesce parameter accordingly. Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> Tested-by: Weiwei Deng <dengweiwei@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e9e6c23 commit b8c17f7

File tree

6 files changed

+149
-11
lines changed

6 files changed

+149
-11
lines changed

drivers/net/ethernet/hisilicon/hns/hnae.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ hnae_init_ring(struct hnae_queue *q, struct hnae_ring *ring, int flags)
202202
ring->q = q;
203203
ring->flags = flags;
204204
spin_lock_init(&ring->lock);
205+
ring->coal_param = q->handle->coal_param;
205206
assert(!ring->desc && !ring->desc_cb && !ring->desc_dma_addr);
206207

207208
/* not matter for tx or rx ring, the ntc and ntc start from 0 */

drivers/net/ethernet/hisilicon/hns/hnae.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ do { \
8989

9090
#define RCB_RING_NAME_LEN 16
9191

92+
#define HNAE_LOWEST_LATENCY_COAL_PARAM 30
93+
#define HNAE_LOW_LATENCY_COAL_PARAM 80
94+
#define HNAE_BULK_LATENCY_COAL_PARAM 150
95+
9296
enum hnae_led_state {
9397
HNAE_LED_INACTIVE,
9498
HNAE_LED_ACTIVE,
@@ -292,6 +296,12 @@ struct hnae_ring {
292296

293297
int flags; /* ring attribute */
294298
int irq_init_flag;
299+
300+
/* total rx bytes after last rx rate calucated */
301+
u64 coal_last_rx_bytes;
302+
unsigned long coal_last_jiffies;
303+
u32 coal_param;
304+
u32 coal_rx_rate; /* rx rate in MB */
295305
};
296306

297307
#define ring_ptr_move_fw(ring, p) \
@@ -548,8 +558,13 @@ struct hnae_handle {
548558
u32 if_support;
549559
int q_num;
550560
int vf_id;
561+
unsigned long coal_last_jiffies;
562+
u32 coal_param; /* self adapt coalesce param */
563+
/* the ring index of last ring that set coal param */
564+
u32 coal_ring_idx;
551565
u32 eport_id;
552566
u32 dport_id; /* v2 tx bd should fill the dport_id */
567+
bool coal_adapt_en;
553568
enum hnae_port_type port_type;
554569
enum hnae_media_type media_type;
555570
struct list_head node; /* list to hnae_ae_dev->handle_list */

drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev,
9999
ae_handle->owner_dev = dsaf_dev->dev;
100100
ae_handle->dev = dev;
101101
ae_handle->q_num = qnum_per_vf;
102+
ae_handle->coal_param = HNAE_LOWEST_LATENCY_COAL_PARAM;
102103

103104
/* find ring pair, and set vf id*/
104105
for (ae_handle->vf_id = 0;

drivers/net/ethernet/hisilicon/hns/hns_enet.c

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,112 @@ static int hns_desc_unused(struct hnae_ring *ring)
812812
return ((ntc >= ntu) ? 0 : ring->desc_num) + ntc - ntu;
813813
}
814814

815+
#define HNS_LOWEST_LATENCY_RATE 27 /* 27 MB/s */
816+
#define HNS_LOW_LATENCY_RATE 80 /* 80 MB/s */
817+
818+
#define HNS_COAL_BDNUM 3
819+
820+
static u32 hns_coal_rx_bdnum(struct hnae_ring *ring)
821+
{
822+
bool coal_enable = ring->q->handle->coal_adapt_en;
823+
824+
if (coal_enable &&
825+
ring->coal_last_rx_bytes > HNS_LOWEST_LATENCY_RATE)
826+
return HNS_COAL_BDNUM;
827+
else
828+
return 0;
829+
}
830+
831+
static void hns_update_rx_rate(struct hnae_ring *ring)
832+
{
833+
bool coal_enable = ring->q->handle->coal_adapt_en;
834+
u32 time_passed_ms;
835+
u64 total_bytes;
836+
837+
if (!coal_enable ||
838+
time_before(jiffies, ring->coal_last_jiffies + (HZ >> 4)))
839+
return;
840+
841+
/* ring->stats.rx_bytes overflowed */
842+
if (ring->coal_last_rx_bytes > ring->stats.rx_bytes) {
843+
ring->coal_last_rx_bytes = ring->stats.rx_bytes;
844+
ring->coal_last_jiffies = jiffies;
845+
return;
846+
}
847+
848+
total_bytes = ring->stats.rx_bytes - ring->coal_last_rx_bytes;
849+
time_passed_ms = jiffies_to_msecs(jiffies - ring->coal_last_jiffies);
850+
ring->coal_rx_rate = (total_bytes / time_passed_ms) >> 10;
851+
852+
ring->coal_last_rx_bytes = ring->stats.rx_bytes;
853+
ring->coal_last_jiffies = jiffies;
854+
}
855+
856+
/**
857+
* smooth_alg - smoothing algrithm for adjusting coalesce parameter
858+
**/
859+
static u32 smooth_alg(u32 new_param, u32 old_param)
860+
{
861+
u32 gap = (new_param > old_param) ? new_param - old_param
862+
: old_param - new_param;
863+
864+
if (gap > 8)
865+
gap >>= 3;
866+
867+
if (new_param > old_param)
868+
return old_param + gap;
869+
else
870+
return old_param - gap;
871+
}
872+
873+
/**
874+
* hns_nic_adp_coalesce - self adapte coalesce according to rx rate
875+
* @ring_data: pointer to hns_nic_ring_data
876+
**/
877+
static void hns_nic_adpt_coalesce(struct hns_nic_ring_data *ring_data)
878+
{
879+
struct hnae_ring *ring = ring_data->ring;
880+
struct hnae_handle *handle = ring->q->handle;
881+
u32 new_coal_param, old_coal_param = ring->coal_param;
882+
883+
if (ring->coal_rx_rate < HNS_LOWEST_LATENCY_RATE)
884+
new_coal_param = HNAE_LOWEST_LATENCY_COAL_PARAM;
885+
else if (ring->coal_rx_rate < HNS_LOW_LATENCY_RATE)
886+
new_coal_param = HNAE_LOW_LATENCY_COAL_PARAM;
887+
else
888+
new_coal_param = HNAE_BULK_LATENCY_COAL_PARAM;
889+
890+
if (new_coal_param == old_coal_param &&
891+
new_coal_param == handle->coal_param)
892+
return;
893+
894+
new_coal_param = smooth_alg(new_coal_param, old_coal_param);
895+
ring->coal_param = new_coal_param;
896+
897+
/**
898+
* Because all ring in one port has one coalesce param, when one ring
899+
* calculate its own coalesce param, it cannot write to hardware at
900+
* once. There are three conditions as follows:
901+
* 1. current ring's coalesce param is larger than the hardware.
902+
* 2. or ring which adapt last time can change again.
903+
* 3. timeout.
904+
*/
905+
if (new_coal_param == handle->coal_param) {
906+
handle->coal_last_jiffies = jiffies;
907+
handle->coal_ring_idx = ring_data->queue_index;
908+
} else if (new_coal_param > handle->coal_param ||
909+
handle->coal_ring_idx == ring_data->queue_index ||
910+
time_after(jiffies, handle->coal_last_jiffies + (HZ >> 4))) {
911+
handle->dev->ops->set_coalesce_usecs(handle,
912+
new_coal_param);
913+
handle->dev->ops->set_coalesce_frames(handle,
914+
1, new_coal_param);
915+
handle->coal_param = new_coal_param;
916+
handle->coal_ring_idx = ring_data->queue_index;
917+
handle->coal_last_jiffies = jiffies;
918+
}
919+
}
920+
815921
static int hns_nic_rx_poll_one(struct hns_nic_ring_data *ring_data,
816922
int budget, void *v)
817923
{
@@ -868,33 +974,45 @@ static bool hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data)
868974
{
869975
struct hnae_ring *ring = ring_data->ring;
870976
int num = 0;
977+
bool rx_stopped;
871978

872-
ring_data->ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
979+
hns_update_rx_rate(ring);
873980

874981
/* for hardware bug fixed */
982+
ring_data->ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
875983
num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
876984

877-
if (num > 0) {
985+
if (num <= hns_coal_rx_bdnum(ring)) {
986+
if (ring->q->handle->coal_adapt_en)
987+
hns_nic_adpt_coalesce(ring_data);
988+
989+
rx_stopped = true;
990+
} else {
878991
ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
879992
ring_data->ring, 1);
880993

881-
return false;
882-
} else {
883-
return true;
994+
rx_stopped = false;
884995
}
996+
997+
return rx_stopped;
885998
}
886999

8871000
static bool hns_nic_rx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
8881001
{
8891002
struct hnae_ring *ring = ring_data->ring;
8901003
int num;
8911004

1005+
hns_update_rx_rate(ring);
8921006
num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
8931007

894-
if (!num)
1008+
if (num <= hns_coal_rx_bdnum(ring)) {
1009+
if (ring->q->handle->coal_adapt_en)
1010+
hns_nic_adpt_coalesce(ring_data);
1011+
8951012
return true;
896-
else
897-
return false;
1013+
}
1014+
1015+
return false;
8981016
}
8991017

9001018
static inline void hns_nic_reclaim_one_desc(struct hnae_ring *ring,

drivers/net/ethernet/hisilicon/hns/hns_enet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct hns_nic_ring_data {
3838
struct hnae_ring *ring;
3939
struct napi_struct napi;
4040
cpumask_t mask; /* affinity mask */
41-
int queue_index;
41+
u32 queue_index;
4242
int (*poll_one)(struct hns_nic_ring_data *, int, void *);
4343
void (*ex_process)(struct hns_nic_ring_data *, struct sk_buff *);
4444
bool (*fini_process)(struct hns_nic_ring_data *);

drivers/net/ethernet/hisilicon/hns/hns_ethtool.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,8 @@ static int hns_get_coalesce(struct net_device *net_dev,
735735

736736
ops = priv->ae_handle->dev->ops;
737737

738-
ec->use_adaptive_rx_coalesce = 1;
739-
ec->use_adaptive_tx_coalesce = 1;
738+
ec->use_adaptive_rx_coalesce = priv->ae_handle->coal_adapt_en;
739+
ec->use_adaptive_tx_coalesce = priv->ae_handle->coal_adapt_en;
740740

741741
if ((!ops->get_coalesce_usecs) ||
742742
(!ops->get_max_coalesced_frames))
@@ -787,6 +787,9 @@ static int hns_set_coalesce(struct net_device *net_dev,
787787
(!ops->set_coalesce_frames))
788788
return -ESRCH;
789789

790+
if (ec->use_adaptive_rx_coalesce != priv->ae_handle->coal_adapt_en)
791+
priv->ae_handle->coal_adapt_en = ec->use_adaptive_rx_coalesce;
792+
790793
rc1 = ops->set_coalesce_usecs(priv->ae_handle,
791794
ec->rx_coalesce_usecs);
792795

0 commit comments

Comments
 (0)