1// SPDX-License-Identifier: GPL-2.0+
2// Copyright (c) 2023 Hisilicon Limited.
3
4#include "hclgevf_main.h"
5#include "hclgevf_regs.h"
6#include "hnae3.h"
7
8static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG,
9 HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG,
10 HCLGE_COMM_NIC_CSQ_DEPTH_REG,
11 HCLGE_COMM_NIC_CSQ_TAIL_REG,
12 HCLGE_COMM_NIC_CSQ_HEAD_REG,
13 HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG,
14 HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG,
15 HCLGE_COMM_NIC_CRQ_DEPTH_REG,
16 HCLGE_COMM_NIC_CRQ_TAIL_REG,
17 HCLGE_COMM_NIC_CRQ_HEAD_REG,
18 HCLGE_COMM_VECTOR0_CMDQ_SRC_REG,
19 HCLGE_COMM_VECTOR0_CMDQ_STATE_REG,
20 HCLGE_COMM_CMDQ_INTR_EN_REG,
21 HCLGE_COMM_CMDQ_INTR_GEN_REG};
22
23static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE,
24 HCLGEVF_RST_ING,
25 HCLGEVF_GRO_EN_REG};
26
27static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG,
28 HCLGEVF_RING_RX_ADDR_H_REG,
29 HCLGEVF_RING_RX_BD_NUM_REG,
30 HCLGEVF_RING_RX_BD_LENGTH_REG,
31 HCLGEVF_RING_RX_MERGE_EN_REG,
32 HCLGEVF_RING_RX_TAIL_REG,
33 HCLGEVF_RING_RX_HEAD_REG,
34 HCLGEVF_RING_RX_FBD_NUM_REG,
35 HCLGEVF_RING_RX_OFFSET_REG,
36 HCLGEVF_RING_RX_FBD_OFFSET_REG,
37 HCLGEVF_RING_RX_STASH_REG,
38 HCLGEVF_RING_RX_BD_ERR_REG,
39 HCLGEVF_RING_TX_ADDR_L_REG,
40 HCLGEVF_RING_TX_ADDR_H_REG,
41 HCLGEVF_RING_TX_BD_NUM_REG,
42 HCLGEVF_RING_TX_PRIORITY_REG,
43 HCLGEVF_RING_TX_TC_REG,
44 HCLGEVF_RING_TX_MERGE_EN_REG,
45 HCLGEVF_RING_TX_TAIL_REG,
46 HCLGEVF_RING_TX_HEAD_REG,
47 HCLGEVF_RING_TX_FBD_NUM_REG,
48 HCLGEVF_RING_TX_OFFSET_REG,
49 HCLGEVF_RING_TX_EBD_NUM_REG,
50 HCLGEVF_RING_TX_EBD_OFFSET_REG,
51 HCLGEVF_RING_TX_BD_ERR_REG,
52 HCLGEVF_RING_EN_REG};
53
54static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG,
55 HCLGEVF_TQP_INTR_GL0_REG,
56 HCLGEVF_TQP_INTR_GL1_REG,
57 HCLGEVF_TQP_INTR_GL2_REG,
58 HCLGEVF_TQP_INTR_RL_REG};
59
60enum hclgevf_reg_tag {
61 HCLGEVF_REG_TAG_CMDQ = 0,
62 HCLGEVF_REG_TAG_COMMON,
63 HCLGEVF_REG_TAG_RING,
64 HCLGEVF_REG_TAG_TQP_INTR,
65};
66
67#pragma pack(4)
68struct hclgevf_reg_tlv {
69 u16 tag;
70 u16 len;
71};
72
73struct hclgevf_reg_header {
74 u64 magic_number;
75 u8 is_vf;
76 u8 rsv[7];
77};
78
79#pragma pack()
80
81#define HCLGEVF_REG_TLV_SIZE sizeof(struct hclgevf_reg_tlv)
82#define HCLGEVF_REG_HEADER_SIZE sizeof(struct hclgevf_reg_header)
83#define HCLGEVF_REG_TLV_SPACE (sizeof(struct hclgevf_reg_tlv) / sizeof(u32))
84#define HCLGEVF_REG_HEADER_SPACE (sizeof(struct hclgevf_reg_header) / sizeof(u32))
85#define HCLGEVF_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */
86
87static u32 hclgevf_reg_get_header(void *data)
88{
89 struct hclgevf_reg_header *header = data;
90
91 header->magic_number = HCLGEVF_REG_MAGIC_NUMBER;
92 header->is_vf = 0x1;
93
94 return HCLGEVF_REG_HEADER_SPACE;
95}
96
97static u32 hclgevf_reg_get_tlv(u32 tag, u32 regs_num, void *data)
98{
99 struct hclgevf_reg_tlv *tlv = data;
100
101 tlv->tag = tag;
102 tlv->len = regs_num * sizeof(u32) + HCLGEVF_REG_TLV_SIZE;
103
104 return HCLGEVF_REG_TLV_SPACE;
105}
106
107int hclgevf_get_regs_len(struct hnae3_handle *handle)
108{
109 struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
110 int cmdq_len, common_len, ring_len, tqp_intr_len;
111
112 cmdq_len = HCLGEVF_REG_TLV_SIZE + sizeof(cmdq_reg_addr_list);
113 common_len = HCLGEVF_REG_TLV_SIZE + sizeof(common_reg_addr_list);
114 ring_len = HCLGEVF_REG_TLV_SIZE + sizeof(ring_reg_addr_list);
115 tqp_intr_len = HCLGEVF_REG_TLV_SIZE + sizeof(tqp_intr_reg_addr_list);
116
117 /* return the total length of all register values */
118 return HCLGEVF_REG_HEADER_SIZE + cmdq_len + common_len +
119 tqp_intr_len * (hdev->num_msi_used - 1) +
120 ring_len * hdev->num_tqps;
121}
122
123void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
124 void *data)
125{
126#define HCLGEVF_RING_REG_OFFSET 0x200
127#define HCLGEVF_RING_INT_REG_OFFSET 0x4
128
129 struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
130 int i, j, reg_um;
131 u32 *reg = data;
132
133 *version = hdev->fw_version;
134 reg += hclgevf_reg_get_header(data: reg);
135
136 /* fetching per-VF registers values from VF PCIe register space */
137 reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32);
138 reg += hclgevf_reg_get_tlv(tag: HCLGEVF_REG_TAG_CMDQ, regs_num: reg_um, data: reg);
139 for (i = 0; i < reg_um; i++)
140 *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
141
142 reg_um = sizeof(common_reg_addr_list) / sizeof(u32);
143 reg += hclgevf_reg_get_tlv(tag: HCLGEVF_REG_TAG_COMMON, regs_num: reg_um, data: reg);
144 for (i = 0; i < reg_um; i++)
145 *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]);
146
147 reg_um = sizeof(ring_reg_addr_list) / sizeof(u32);
148 for (j = 0; j < hdev->num_tqps; j++) {
149 reg += hclgevf_reg_get_tlv(tag: HCLGEVF_REG_TAG_RING, regs_num: reg_um, data: reg);
150 for (i = 0; i < reg_um; i++)
151 *reg++ = hclgevf_read_dev(&hdev->hw,
152 ring_reg_addr_list[i] +
153 HCLGEVF_RING_REG_OFFSET * j);
154 }
155
156 reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32);
157 for (j = 0; j < hdev->num_msi_used - 1; j++) {
158 reg += hclgevf_reg_get_tlv(tag: HCLGEVF_REG_TAG_TQP_INTR, regs_num: reg_um, data: reg);
159 for (i = 0; i < reg_um; i++)
160 *reg++ = hclgevf_read_dev(&hdev->hw,
161 tqp_intr_reg_addr_list[i] +
162 HCLGEVF_RING_INT_REG_OFFSET * j);
163 }
164}
165

source code of linux/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c