Skip to content

Commit e6ab194

Browse files
Peiyang WangPaolo Abeni
authored andcommitted
net: hns3: default enable tx bounce buffer when smmu enabled
The SMMU engine on HIP09 chip has a hardware issue. SMMU pagetable prefetch features may prefetch and use a invalid PTE even the PTE is valid at that time. This will cause the device trigger fake pagefaults. The solution is to avoid prefetching by adding a SYNC command when smmu mapping a iova. But the performance of nic has a sharp drop. Then we do this workaround, always enable tx bounce buffer, avoid mapping/unmapping on TX path. This issue only affects HNS3, so we always enable tx bounce buffer when smmu enabled to improve performance. Fixes: 295ba23 ("net: hns3: add device version to replace pci revision") Signed-off-by: Peiyang Wang <[email protected]> Signed-off-by: Jian Shen <[email protected]> Signed-off-by: Jijie Shao <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 637f414 commit e6ab194

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

drivers/net/ethernet/hisilicon/hns3/hns3_enet.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/irq.h>
1212
#include <linux/ip.h>
1313
#include <linux/ipv6.h>
14+
#include <linux/iommu.h>
1415
#include <linux/module.h>
1516
#include <linux/pci.h>
1617
#include <linux/skbuff.h>
@@ -1032,6 +1033,8 @@ static bool hns3_can_use_tx_sgl(struct hns3_enet_ring *ring,
10321033
static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring)
10331034
{
10341035
u32 alloc_size = ring->tqp->handle->kinfo.tx_spare_buf_size;
1036+
struct net_device *netdev = ring_to_netdev(ring);
1037+
struct hns3_nic_priv *priv = netdev_priv(netdev);
10351038
struct hns3_tx_spare *tx_spare;
10361039
struct page *page;
10371040
dma_addr_t dma;
@@ -1073,6 +1076,7 @@ static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring)
10731076
tx_spare->buf = page_address(page);
10741077
tx_spare->len = PAGE_SIZE << order;
10751078
ring->tx_spare = tx_spare;
1079+
ring->tx_copybreak = priv->tx_copybreak;
10761080
return;
10771081

10781082
dma_mapping_error:
@@ -4868,6 +4872,30 @@ static void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
48684872
devm_kfree(&pdev->dev, priv->tqp_vector);
48694873
}
48704874

4875+
static void hns3_update_tx_spare_buf_config(struct hns3_nic_priv *priv)
4876+
{
4877+
#define HNS3_MIN_SPARE_BUF_SIZE (2 * 1024 * 1024)
4878+
#define HNS3_MAX_PACKET_SIZE (64 * 1024)
4879+
4880+
struct iommu_domain *domain = iommu_get_domain_for_dev(priv->dev);
4881+
struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(priv->ae_handle);
4882+
struct hnae3_handle *handle = priv->ae_handle;
4883+
4884+
if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3)
4885+
return;
4886+
4887+
if (!(domain && iommu_is_dma_domain(domain)))
4888+
return;
4889+
4890+
priv->min_tx_copybreak = HNS3_MAX_PACKET_SIZE;
4891+
priv->min_tx_spare_buf_size = HNS3_MIN_SPARE_BUF_SIZE;
4892+
4893+
if (priv->tx_copybreak < priv->min_tx_copybreak)
4894+
priv->tx_copybreak = priv->min_tx_copybreak;
4895+
if (handle->kinfo.tx_spare_buf_size < priv->min_tx_spare_buf_size)
4896+
handle->kinfo.tx_spare_buf_size = priv->min_tx_spare_buf_size;
4897+
}
4898+
48714899
static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
48724900
unsigned int ring_type)
48734901
{
@@ -5101,6 +5129,7 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv)
51015129
int i, j;
51025130
int ret;
51035131

5132+
hns3_update_tx_spare_buf_config(priv);
51045133
for (i = 0; i < ring_num; i++) {
51055134
ret = hns3_alloc_ring_memory(&priv->ring[i]);
51065135
if (ret) {
@@ -5305,6 +5334,8 @@ static int hns3_client_init(struct hnae3_handle *handle)
53055334
priv->ae_handle = handle;
53065335
priv->tx_timeout_count = 0;
53075336
priv->max_non_tso_bd_num = ae_dev->dev_specs.max_non_tso_bd_num;
5337+
priv->min_tx_copybreak = 0;
5338+
priv->min_tx_spare_buf_size = 0;
53085339
set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
53095340

53105341
handle->msg_enable = netif_msg_init(debug, DEFAULT_MSG_LEVEL);

drivers/net/ethernet/hisilicon/hns3/hns3_enet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ struct hns3_nic_priv {
596596
struct hns3_enet_coalesce rx_coal;
597597
u32 tx_copybreak;
598598
u32 rx_copybreak;
599+
u32 min_tx_copybreak;
600+
u32 min_tx_spare_buf_size;
599601
};
600602

601603
union l3_hdr_info {

drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,31 @@ static int hns3_set_tx_spare_buf_size(struct net_device *netdev,
19331933
return ret;
19341934
}
19351935

1936+
static int hns3_check_tx_copybreak(struct net_device *netdev, u32 copybreak)
1937+
{
1938+
struct hns3_nic_priv *priv = netdev_priv(netdev);
1939+
1940+
if (copybreak < priv->min_tx_copybreak) {
1941+
netdev_err(netdev, "tx copybreak %u should be no less than %u!\n",
1942+
copybreak, priv->min_tx_copybreak);
1943+
return -EINVAL;
1944+
}
1945+
return 0;
1946+
}
1947+
1948+
static int hns3_check_tx_spare_buf_size(struct net_device *netdev, u32 buf_size)
1949+
{
1950+
struct hns3_nic_priv *priv = netdev_priv(netdev);
1951+
1952+
if (buf_size < priv->min_tx_spare_buf_size) {
1953+
netdev_err(netdev,
1954+
"tx spare buf size %u should be no less than %u!\n",
1955+
buf_size, priv->min_tx_spare_buf_size);
1956+
return -EINVAL;
1957+
}
1958+
return 0;
1959+
}
1960+
19361961
static int hns3_set_tunable(struct net_device *netdev,
19371962
const struct ethtool_tunable *tuna,
19381963
const void *data)
@@ -1949,6 +1974,10 @@ static int hns3_set_tunable(struct net_device *netdev,
19491974

19501975
switch (tuna->id) {
19511976
case ETHTOOL_TX_COPYBREAK:
1977+
ret = hns3_check_tx_copybreak(netdev, *(u32 *)data);
1978+
if (ret)
1979+
return ret;
1980+
19521981
priv->tx_copybreak = *(u32 *)data;
19531982

19541983
for (i = 0; i < h->kinfo.num_tqps; i++)
@@ -1963,6 +1992,10 @@ static int hns3_set_tunable(struct net_device *netdev,
19631992

19641993
break;
19651994
case ETHTOOL_TX_COPYBREAK_BUF_SIZE:
1995+
ret = hns3_check_tx_spare_buf_size(netdev, *(u32 *)data);
1996+
if (ret)
1997+
return ret;
1998+
19661999
old_tx_spare_buf_size = h->kinfo.tx_spare_buf_size;
19672000
new_tx_spare_buf_size = *(u32 *)data;
19682001
netdev_info(netdev, "request to set tx spare buf size from %u to %u\n",

0 commit comments

Comments
 (0)