334 lines
11 KiB
Diff
334 lines
11 KiB
Diff
From d7106b08a3618f542ba1beb3ceeda96c85878e03 Mon Sep 17 00:00:00 2001
|
|
From: Yufeng Mo <moyufeng@huawei.com>
|
|
Date: Mon, 17 Jan 2022 21:07:58 +0800
|
|
Subject: [PATCH 176/283] net: hns3: add support for TX push mode
|
|
|
|
driver inclusion
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EN3D
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
For the device that supports the TX push capability, the BD can
|
|
be directly copied to the device memory. However, due to hardware
|
|
restrictions, the push mode can be used only when there are no
|
|
more than two BDs, otherwise, the doorbell mode based on device
|
|
memory is used.
|
|
|
|
Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
|
|
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Reviewed-by: Yue Haibing <yuehaibing@huawei.com>
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
|
|
Conflicts:
|
|
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
---
|
|
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 +
|
|
.../net/ethernet/hisilicon/hns3/hns3_enet.c | 82 +++++++++++++++++--
|
|
.../net/ethernet/hisilicon/hns3/hns3_enet.h | 4 +
|
|
.../ethernet/hisilicon/hns3/hns3_ethtool.c | 2 +
|
|
.../hisilicon/hns3/hns3pf/hclge_main.c | 9 ++
|
|
.../hisilicon/hns3/hns3pf/hclge_main.h | 9 ++
|
|
.../hisilicon/hns3/hns3vf/hclgevf_main.c | 9 ++
|
|
.../hisilicon/hns3/hns3vf/hclgevf_main.h | 13 ++-
|
|
include/asm-generic/barrier.h | 4 +
|
|
9 files changed, 123 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
index 4f77d80b01f4..60918a9c3953 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
|
|
@@ -167,6 +167,7 @@ struct hnae3_handle;
|
|
|
|
struct hnae3_queue {
|
|
void __iomem *io_base;
|
|
+ void __iomem *mem_base;
|
|
struct hnae3_ae_algo *ae_algo;
|
|
struct hnae3_handle *handle;
|
|
int tqp_index; /* index in a handle */
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
index 19ba800afc6c..43b38e267e5b 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
@@ -1709,9 +1709,73 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
|
|
return bd_num;
|
|
}
|
|
|
|
+static void hns3_tx_push_bd(struct hns3_enet_ring *ring, int num)
|
|
+{
|
|
+#define HNS3_BYTES_PER_64BIT 8
|
|
+
|
|
+ struct hns3_desc desc[HNS3_MAX_PUSH_BD_NUM] = {};
|
|
+ int offset = 0;
|
|
+
|
|
+ /* make sure everything is visible to device before
|
|
+ * excuting tx push or updating doorbell
|
|
+ */
|
|
+ dma_wmb();
|
|
+
|
|
+ do {
|
|
+ int idx = (ring->next_to_use - num + ring->desc_num) %
|
|
+ ring->desc_num;
|
|
+
|
|
+ u64_stats_update_begin(&ring->syncp);
|
|
+ ring->stats.tx_push++;
|
|
+ u64_stats_update_end(&ring->syncp);
|
|
+ memcpy(&desc[offset], &ring->desc[idx],
|
|
+ sizeof(struct hns3_desc));
|
|
+ offset++;
|
|
+ } while (--num);
|
|
+
|
|
+ __iowrite64_copy(ring->tqp->mem_base, desc,
|
|
+ (sizeof(struct hns3_desc) * HNS3_MAX_PUSH_BD_NUM) /
|
|
+ HNS3_BYTES_PER_64BIT);
|
|
+
|
|
+ io_stop_wc();
|
|
+}
|
|
+
|
|
+static void hns3_tx_mem_doorbell(struct hns3_enet_ring *ring)
|
|
+{
|
|
+#define HNS3_MEM_DOORBELL_OFFSET 64
|
|
+
|
|
+ __le64 bd_num = cpu_to_le64((u64)ring->pending_buf);
|
|
+
|
|
+ /* make sure everything is visible to device before
|
|
+ * excuting tx push or updating doorbell
|
|
+ */
|
|
+ dma_wmb();
|
|
+
|
|
+ __iowrite64_copy(ring->tqp->mem_base + HNS3_MEM_DOORBELL_OFFSET,
|
|
+ &bd_num, 1);
|
|
+ u64_stats_update_begin(&ring->syncp);
|
|
+ ring->stats.tx_mem_doorbell += ring->pending_buf;
|
|
+ u64_stats_update_end(&ring->syncp);
|
|
+
|
|
+ io_stop_wc();
|
|
+}
|
|
+
|
|
static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
|
|
bool doorbell)
|
|
{
|
|
+ struct net_device *netdev = ring_to_netdev(ring);
|
|
+ struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
+
|
|
+ /* when tx push is enabled, the packet whose number of BD below
|
|
+ * HNS3_MAX_PUSH_BD_NUM can be pushed directly.
|
|
+ */
|
|
+ if (test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state) && num &&
|
|
+ !ring->pending_buf && num <= HNS3_MAX_PUSH_BD_NUM && doorbell) {
|
|
+ hns3_tx_push_bd(ring, num);
|
|
+ WRITE_ONCE(ring->last_to_use, ring->next_to_use);
|
|
+ return;
|
|
+ }
|
|
+
|
|
ring->pending_buf += num;
|
|
|
|
if (!doorbell) {
|
|
@@ -1721,17 +1785,14 @@ static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
|
|
return;
|
|
}
|
|
|
|
- if (!ring->pending_buf)
|
|
- return;
|
|
-
|
|
- /* This smp_store_release() pairs with smp_load_aquire() in
|
|
- * hns3_nic_reclaim_desc(). Ensure that the BD valid bit is updated.
|
|
- */
|
|
- smp_store_release(&ring->last_to_use, ring->next_to_use);
|
|
+ if (ring->tqp->mem_base)
|
|
+ hns3_tx_mem_doorbell(ring);
|
|
+ else
|
|
+ writel(ring->pending_buf,
|
|
+ ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG);
|
|
|
|
- writel(ring->pending_buf,
|
|
- ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG);
|
|
ring->pending_buf = 0;
|
|
+ WRITE_ONCE(ring->last_to_use, ring->next_to_use);
|
|
}
|
|
|
|
static void hns3_tsyn(struct net_device *netdev, struct sk_buff *skb,
|
|
@@ -4694,6 +4755,9 @@ static void hns3_state_init(struct hnae3_handle *handle)
|
|
|
|
set_bit(HNS3_NIC_STATE_INITED, &priv->state);
|
|
|
|
+ if (test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps))
|
|
+ set_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state);
|
|
+
|
|
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3)
|
|
set_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->supported_pflags);
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
|
|
index f889ec9fc24e..2377e69818a5 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
|
|
@@ -24,6 +24,8 @@ enum hns3_nic_state {
|
|
HNS3_NIC_STATE_MAX
|
|
};
|
|
|
|
+#define HNS3_MAX_PUSH_BD_NUM 2
|
|
+
|
|
#define HNS3_RING_RX_RING_BASEADDR_L_REG 0x00000
|
|
#define HNS3_RING_RX_RING_BASEADDR_H_REG 0x00004
|
|
#define HNS3_RING_RX_RING_BD_NUM_REG 0x00008
|
|
@@ -397,6 +399,8 @@ struct ring_stats {
|
|
u64 tx_pkts;
|
|
u64 tx_bytes;
|
|
u64 tx_more;
|
|
+ u64 tx_push;
|
|
+ u64 tx_mem_doorbell;
|
|
u64 restart_queue;
|
|
u64 tx_busy;
|
|
u64 tx_copy;
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
index a7f4820f6f8c..3646738ef4bc 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
@@ -27,6 +27,8 @@ static const struct hns3_stats hns3_txq_stats[] = {
|
|
HNS3_TQP_STAT("packets", tx_pkts),
|
|
HNS3_TQP_STAT("bytes", tx_bytes),
|
|
HNS3_TQP_STAT("more", tx_more),
|
|
+ HNS3_TQP_STAT("push", tx_push),
|
|
+ HNS3_TQP_STAT("mem_doorbell", tx_mem_doorbell),
|
|
HNS3_TQP_STAT("wake", restart_queue),
|
|
HNS3_TQP_STAT("busy", tx_busy),
|
|
HNS3_TQP_STAT("copy", tx_copy),
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index 3ff2eb9fcf5f..691fbbb77619 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -1683,6 +1683,7 @@ static int hclge_config_gro(struct hclge_dev *hdev)
|
|
static int hclge_alloc_tqps(struct hclge_dev *hdev)
|
|
{
|
|
struct hclge_tqp *tqp;
|
|
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
|
|
int i;
|
|
|
|
hdev->htqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
|
|
@@ -1703,6 +1704,14 @@ static int hclge_alloc_tqps(struct hclge_dev *hdev)
|
|
tqp->q.io_base = hdev->hw.io_base + HCLGE_TQP_REG_OFFSET +
|
|
i * HCLGE_TQP_REG_SIZE;
|
|
|
|
+ /* when device supports tx push and has device memory,
|
|
+ * the queue can execute push mode or doorbell mode on
|
|
+ * device memory.
|
|
+ */
|
|
+ if (test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps))
|
|
+ tqp->q.mem_base = hdev->hw.hw.mem_base +
|
|
+ HCLGE_TQP_MEM_OFFSET(hdev, i);
|
|
+
|
|
tqp++;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
index 7ba42bbcf370..973b4f3de627 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
@@ -196,6 +196,14 @@ enum HLCGE_PORT_TYPE {
|
|
#define HCLGE_VECTOR0_ALL_MSIX_ERR_B 6U
|
|
#define HCLGE_TRIGGER_IMP_RESET_B 7U
|
|
|
|
+#define HCLGE_TQP_MEM_SIZE 0x10000
|
|
+#define HCLGE_MEM_BAR 4
|
|
+/* in the bar4, the first half is for roce, and the second half is for nic */
|
|
+#define HCLGE_NIC_MEM_OFFSET(hdev) \
|
|
+ (pci_resource_len((hdev)->pdev, HCLGE_MEM_BAR) >> 1)
|
|
+#define HCLGE_TQP_MEM_OFFSET(hdev, i) \
|
|
+ (HCLGE_NIC_MEM_OFFSET(hdev) + HCLGE_TQP_MEM_SIZE * (i))
|
|
+
|
|
#define HCLGE_MAC_DEFAULT_FRAME \
|
|
(ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN)
|
|
#define HCLGE_MAC_MIN_FRAME 64
|
|
@@ -296,6 +304,7 @@ struct hclge_mac {
|
|
};
|
|
|
|
struct hclge_hw {
|
|
+ struct hclge_comm_hw hw;
|
|
void __iomem *io_base;
|
|
void __iomem *mem_base;
|
|
struct hclge_mac mac;
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
index ffac4a4aa66a..4dbfd2daa7e2 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
@@ -394,6 +394,7 @@ static int hclgevf_get_pf_media_type(struct hclgevf_dev *hdev)
|
|
static int hclgevf_alloc_tqps(struct hclgevf_dev *hdev)
|
|
{
|
|
struct hclgevf_tqp *tqp;
|
|
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
|
|
int i;
|
|
|
|
hdev->htqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
|
|
@@ -414,6 +415,14 @@ static int hclgevf_alloc_tqps(struct hclgevf_dev *hdev)
|
|
tqp->q.io_base = hdev->hw.io_base + HCLGEVF_TQP_REG_OFFSET +
|
|
i * HCLGEVF_TQP_REG_SIZE;
|
|
|
|
+ /* when device supports tx push and has device memory,
|
|
+ * the queue can execute push mode or doorbell mode on
|
|
+ * device memory.
|
|
+ */
|
|
+ if (test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps))
|
|
+ tqp->q.mem_base = hdev->hw.hw.mem_base +
|
|
+ HCLGEVF_TQP_MEM_OFFSET(hdev, i);
|
|
+
|
|
tqp++;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
index a9624b9adcfd..97e9834c6de5 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
@@ -126,6 +126,16 @@
|
|
#define HCLGEVF_RSS_INPUT_TUPLE_SCTP6 \
|
|
(HCLGEVF_D_IP_BIT | HCLGEVF_S_IP_BIT | HCLGEVF_V_TAG_BIT)
|
|
|
|
+#define HCLGEVF_TQP_MEM_SIZE 0x10000
|
|
+#define HCLGEVF_MEM_BAR 4
|
|
+/* in the bar4, the first half is for roce, and the second half is for nic */
|
|
+#define HCLGEVF_NIC_MEM_OFFSET(hdev) \
|
|
+ (pci_resource_len((hdev)->pdev, HCLGEVF_MEM_BAR) >> 1)
|
|
+#define HCLGEVF_TQP_MEM_OFFSET(hdev, i) \
|
|
+ (HCLGEVF_NIC_MEM_OFFSET(hdev) + HCLGEVF_TQP_MEM_SIZE * (i))
|
|
+
|
|
+#define HCLGEVF_MAC_MAX_FRAME 9728
|
|
+
|
|
#define HCLGEVF_STATS_TIMER_INTERVAL 36U
|
|
|
|
enum hclgevf_evt_cause {
|
|
@@ -167,12 +177,13 @@ struct hclgevf_mac {
|
|
};
|
|
|
|
struct hclgevf_hw {
|
|
+ struct hclge_comm_hw hw;
|
|
void __iomem *io_base;
|
|
void __iomem *mem_base;
|
|
int num_vec;
|
|
struct hclgevf_cmq cmq;
|
|
struct hclgevf_mac mac;
|
|
- void *hdev; /* hchgevf device it is part of */
|
|
+ void *hdev; /* hclgevf device it is par of */
|
|
};
|
|
|
|
/* TQP stats */
|
|
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
|
|
index 2cafdbb9ae4c..ad7f17434dfc 100644
|
|
--- a/include/asm-generic/barrier.h
|
|
+++ b/include/asm-generic/barrier.h
|
|
@@ -261,5 +261,9 @@ do { \
|
|
})
|
|
#endif
|
|
|
|
+#ifndef io_stop_wc
|
|
+#define io_stop_wc() do { } while (0)
|
|
+#endif
|
|
+
|
|
#endif /* !__ASSEMBLY__ */
|
|
#endif /* __ASM_GENERIC_BARRIER_H */
|
|
--
|
|
2.34.1
|
|
|