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 
8 static 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 
23 static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE,
24 					   HCLGEVF_RST_ING,
25 					   HCLGEVF_GRO_EN_REG};
26 
27 static 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 
54 static 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 
60 enum 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)
68 struct hclgevf_reg_tlv {
69 	u16 tag;
70 	u16 len;
71 };
72 
73 struct 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 
87 static 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 
97 static 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 
107 int 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 
123 void 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(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(HCLGEVF_REG_TAG_CMDQ, reg_um, 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(HCLGEVF_REG_TAG_COMMON, reg_um, 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(HCLGEVF_REG_TAG_RING, reg_um, 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(HCLGEVF_REG_TAG_TQP_INTR, reg_um, 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