diff options
author | lipeng <lipeng321@huawei.com> | 2017-04-01 12:03:47 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-04-03 14:48:43 -0700 |
commit | 820c90cb3e2e452c80824391953cab9d5b5af154 (patch) | |
tree | 084e557cd36de868cc7094d3899a57170b9de5d7 /drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | |
parent | 76b588bc523bee796834ebd319f6a71ad3eddbae (diff) | |
download | linux-820c90cb3e2e452c80824391953cab9d5b5af154.tar.bz2 |
net: hns: Avoid Hip06 chip TX packet line bug
There is a bug on Hip06 that tx ring interrupts packets count will be
clear when drivers send data to tx ring, so that the tx packets count
will never upgrade to packets line, and cause the interrupts engendered
was delayed.
Sometimes, it will cause sending performance lower than expected.
To fix this bug, we set tx ring interrupts packets line to 1 forever,
to avoid count clear. And set the gap time to 20us, to solve the problem
that too many interrupts engendered when packets line is 1.
This patch could advance the send performance on ARM from 6.6G to 9.37G
when an iperf send thread on ARM and an iperf send thread on X86 for XGE.
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c')
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 101 |
1 files changed, 75 insertions, 26 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index a6ab1680d294..9b66057f08c6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -254,7 +254,7 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_TX_RING_BD_NUM_REG, ring_pair->port_id_in_comm); dsaf_write_dev(q, RCB_RING_TX_RING_PKTLINE_REG, - ring_pair->port_id_in_comm); + ring_pair->port_id_in_comm + HNS_RCB_TX_PKTLINE_OFFSET); } } @@ -284,13 +284,27 @@ static void hns_rcb_set_port_desc_cnt(struct rcb_common_cb *rcb_common, static void hns_rcb_set_port_timeout( struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout) { - if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) { dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, timeout * HNS_RCB_CLK_FREQ_MHZ); - else + } else if (!HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) { + if (timeout > HNS_RCB_DEF_GAP_TIME_USECS) + dsaf_write_dev(rcb_common, + RCB_PORT_INT_GAPTIME_REG + port_idx * 4, + HNS_RCB_DEF_GAP_TIME_USECS); + else + dsaf_write_dev(rcb_common, + RCB_PORT_INT_GAPTIME_REG + port_idx * 4, + timeout); + dsaf_write_dev(rcb_common, RCB_PORT_CFG_OVERTIME_REG + port_idx * 4, timeout); + } else { + dsaf_write_dev(rcb_common, + RCB_PORT_CFG_OVERTIME_REG + port_idx * 4, + timeout); + } } static int hns_rcb_common_get_port_num(struct rcb_common_cb *rcb_common) @@ -352,8 +366,12 @@ int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common) for (i = 0; i < port_num; i++) { hns_rcb_set_port_desc_cnt(rcb_common, i, rcb_common->desc_num); - (void)hns_rcb_set_coalesced_frames( - rcb_common, i, HNS_RCB_DEF_COALESCED_FRAMES); + hns_rcb_set_rx_coalesced_frames( + rcb_common, i, HNS_RCB_DEF_RX_COALESCED_FRAMES); + if (!AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver) && + !HNS_DSAF_IS_DEBUG(rcb_common->dsaf_dev)) + hns_rcb_set_tx_coalesced_frames( + rcb_common, i, HNS_RCB_DEF_TX_COALESCED_FRAMES); hns_rcb_set_port_timeout( rcb_common, i, HNS_RCB_DEF_COALESCED_USECS); } @@ -507,19 +525,35 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) } /** - *hns_rcb_get_coalesced_frames - get rcb port coalesced frames + *hns_rcb_get_rx_coalesced_frames - get rcb port rx coalesced frames *@rcb_common: rcb_common device *@port_idx:port id in comm * *Returns: coalesced_frames */ -u32 hns_rcb_get_coalesced_frames( +u32 hns_rcb_get_rx_coalesced_frames( struct rcb_common_cb *rcb_common, u32 port_idx) { return dsaf_read_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4); } /** + *hns_rcb_get_tx_coalesced_frames - get rcb port tx coalesced frames + *@rcb_common: rcb_common device + *@port_idx:port id in comm + * + *Returns: coalesced_frames + */ +u32 hns_rcb_get_tx_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx) +{ + u64 reg; + + reg = RCB_CFG_PKTLINE_REG + (port_idx + HNS_RCB_TX_PKTLINE_OFFSET) * 4; + return dsaf_read_dev(rcb_common, reg); +} + +/** *hns_rcb_get_coalesce_usecs - get rcb port coalesced time_out *@rcb_common: rcb_common device *@port_idx:port id in comm @@ -561,33 +595,47 @@ int hns_rcb_set_coalesce_usecs( return -EINVAL; } } - if (timeout > HNS_RCB_MAX_COALESCED_USECS) { + if (timeout > HNS_RCB_MAX_COALESCED_USECS || timeout == 0) { dev_err(rcb_common->dsaf_dev->dev, - "error: coalesce_usecs setting supports 0~1023us\n"); + "error: coalesce_usecs setting supports 1~1023us\n"); return -EINVAL; } + hns_rcb_set_port_timeout(rcb_common, port_idx, timeout); + return 0; +} - if (!AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) { - if (timeout == 0) - /* set timeout to 0, Disable gap time */ - dsaf_set_reg_field(rcb_common->io_base, - RCB_INT_GAP_TIME_REG + port_idx * 4, - PPE_INT_GAPTIME_M, PPE_INT_GAPTIME_B, - 0); - else - /* set timeout non 0, restore gap time to 1 */ - dsaf_set_reg_field(rcb_common->io_base, - RCB_INT_GAP_TIME_REG + port_idx * 4, - PPE_INT_GAPTIME_M, PPE_INT_GAPTIME_B, - 1); +/** + *hns_rcb_set_tx_coalesced_frames - set rcb coalesced frames + *@rcb_common: rcb_common device + *@port_idx:port id in comm + *@coalesced_frames:tx/rx BD num for coalesced frames + * + * Returns: + * Zero for success, or an error code in case of failure + */ +int hns_rcb_set_tx_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 coalesced_frames) +{ + u32 old_waterline = + hns_rcb_get_tx_coalesced_frames(rcb_common, port_idx); + u64 reg; + + if (coalesced_frames == old_waterline) + return 0; + + if (coalesced_frames != 1) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support tx coalesce_frames setting!\n"); + return -EINVAL; } - hns_rcb_set_port_timeout(rcb_common, port_idx, timeout); + reg = RCB_CFG_PKTLINE_REG + (port_idx + HNS_RCB_TX_PKTLINE_OFFSET) * 4; + dsaf_write_dev(rcb_common, reg, coalesced_frames); return 0; } /** - *hns_rcb_set_coalesced_frames - set rcb coalesced frames + *hns_rcb_set_rx_coalesced_frames - set rcb rx coalesced frames *@rcb_common: rcb_common device *@port_idx:port id in comm *@coalesced_frames:tx/rx BD num for coalesced frames @@ -595,10 +643,11 @@ int hns_rcb_set_coalesce_usecs( * Returns: * Zero for success, or an error code in case of failure */ -int hns_rcb_set_coalesced_frames( +int hns_rcb_set_rx_coalesced_frames( struct rcb_common_cb *rcb_common, u32 port_idx, u32 coalesced_frames) { - u32 old_waterline = hns_rcb_get_coalesced_frames(rcb_common, port_idx); + u32 old_waterline = + hns_rcb_get_rx_coalesced_frames(rcb_common, port_idx); if (coalesced_frames == old_waterline) return 0; |