xref: /linux/drivers/net/ethernet/alibaba/eea/eea_adminq.c (revision 4c45a51e5bf520a0e6189bce1825d44029a4ea32)
1*4c45a51eSXuan Zhuo // SPDX-License-Identifier: GPL-2.0-or-later
2*4c45a51eSXuan Zhuo /*
3*4c45a51eSXuan Zhuo  * Driver for Alibaba Elastic Ethernet Adapter.
4*4c45a51eSXuan Zhuo  *
5*4c45a51eSXuan Zhuo  * Copyright (C) 2025 Alibaba Inc.
6*4c45a51eSXuan Zhuo  */
7*4c45a51eSXuan Zhuo 
8*4c45a51eSXuan Zhuo #include <linux/etherdevice.h>
9*4c45a51eSXuan Zhuo #include <linux/iopoll.h>
10*4c45a51eSXuan Zhuo #include <linux/utsname.h>
11*4c45a51eSXuan Zhuo #include <linux/version.h>
12*4c45a51eSXuan Zhuo 
13*4c45a51eSXuan Zhuo #include "eea_adminq.h"
14*4c45a51eSXuan Zhuo #include "eea_net.h"
15*4c45a51eSXuan Zhuo #include "eea_pci.h"
16*4c45a51eSXuan Zhuo #include "eea_ring.h"
17*4c45a51eSXuan Zhuo 
18*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_CFG_QUERY         ((0 << 8) | 0)
19*4c45a51eSXuan Zhuo 
20*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_QUEUE_CREATE      ((1 << 8) | 0)
21*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_QUEUE_DESTROY_ALL ((1 << 8) | 1)
22*4c45a51eSXuan Zhuo 
23*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_HOST_INFO         ((2 << 8) | 0)
24*4c45a51eSXuan Zhuo 
25*4c45a51eSXuan Zhuo #define EEA_AQ_CMD_DEV_STATUS        ((3 << 8) | 0)
26*4c45a51eSXuan Zhuo 
27*4c45a51eSXuan Zhuo #define EEA_RING_DESC_F_AQ_PHASE     (BIT(15) | BIT(7))
28*4c45a51eSXuan Zhuo 
29*4c45a51eSXuan Zhuo #define EEA_QUEUE_FLAGS_HW_SPLIT_HDR BIT(0)
30*4c45a51eSXuan Zhuo #define EEA_QUEUE_FLAGS_SQCQ         BIT(1)
31*4c45a51eSXuan Zhuo #define EEA_QUEUE_FLAGS_HWTS         BIT(2)
32*4c45a51eSXuan Zhuo 
33*4c45a51eSXuan Zhuo struct eea_aq_create {
34*4c45a51eSXuan Zhuo 	__le32 flags;
35*4c45a51eSXuan Zhuo 	/* queue index.
36*4c45a51eSXuan Zhuo 	 * rx: 0 == qidx % 2
37*4c45a51eSXuan Zhuo 	 * tx: 1 == qidx % 2
38*4c45a51eSXuan Zhuo 	 */
39*4c45a51eSXuan Zhuo 	__le16 qidx;
40*4c45a51eSXuan Zhuo 	/* the depth of the queue */
41*4c45a51eSXuan Zhuo 	__le16 depth;
42*4c45a51eSXuan Zhuo 	/*  0: without SPLIT HDR
43*4c45a51eSXuan Zhuo 	 *  1: 128B
44*4c45a51eSXuan Zhuo 	 *  2: 256B
45*4c45a51eSXuan Zhuo 	 *  3: 512B
46*4c45a51eSXuan Zhuo 	 */
47*4c45a51eSXuan Zhuo 	u8 hdr_buf_size;
48*4c45a51eSXuan Zhuo 	u8 sq_desc_size;
49*4c45a51eSXuan Zhuo 	u8 cq_desc_size;
50*4c45a51eSXuan Zhuo 	u8 reserve0;
51*4c45a51eSXuan Zhuo 	/* The vector for the irq. rx,tx share the same vector */
52*4c45a51eSXuan Zhuo 	__le16 msix_vector;
53*4c45a51eSXuan Zhuo 	__le16 reserve;
54*4c45a51eSXuan Zhuo 	/* sq ring cfg. */
55*4c45a51eSXuan Zhuo 	__le32 sq_addr_low;
56*4c45a51eSXuan Zhuo 	__le32 sq_addr_high;
57*4c45a51eSXuan Zhuo 	/* cq ring cfg. Just valid when flags include EEA_QUEUE_FLAGS_SQCQ. */
58*4c45a51eSXuan Zhuo 	__le32 cq_addr_low;
59*4c45a51eSXuan Zhuo 	__le32 cq_addr_high;
60*4c45a51eSXuan Zhuo };
61*4c45a51eSXuan Zhuo 
62*4c45a51eSXuan Zhuo struct eea_aq_queue_drv_status {
63*4c45a51eSXuan Zhuo 	__le16 qidx;
64*4c45a51eSXuan Zhuo 
65*4c45a51eSXuan Zhuo 	__le16 sq_head;
66*4c45a51eSXuan Zhuo 	__le16 cq_head;
67*4c45a51eSXuan Zhuo 	__le16 reserved;
68*4c45a51eSXuan Zhuo };
69*4c45a51eSXuan Zhuo 
70*4c45a51eSXuan Zhuo #define EEA_OS_DISTRO		0
71*4c45a51eSXuan Zhuo #define EEA_DRV_TYPE		0
72*4c45a51eSXuan Zhuo #define EEA_OS_LINUX		1
73*4c45a51eSXuan Zhuo #define EEA_SPEC_VER_MAJOR	1
74*4c45a51eSXuan Zhuo #define EEA_SPEC_VER_MINOR	0
75*4c45a51eSXuan Zhuo 
76*4c45a51eSXuan Zhuo struct eea_aq_host_info_cfg {
77*4c45a51eSXuan Zhuo 	__le16	os_type;
78*4c45a51eSXuan Zhuo 	__le16	os_dist;
79*4c45a51eSXuan Zhuo 	__le16	drv_type;
80*4c45a51eSXuan Zhuo 
81*4c45a51eSXuan Zhuo 	__le16	kern_ver_major;
82*4c45a51eSXuan Zhuo 	__le16	kern_ver_minor;
83*4c45a51eSXuan Zhuo 	__le16	kern_ver_sub_minor;
84*4c45a51eSXuan Zhuo 
85*4c45a51eSXuan Zhuo 	__le16	drv_ver_major;
86*4c45a51eSXuan Zhuo 	__le16	drv_ver_minor;
87*4c45a51eSXuan Zhuo 	__le16	drv_ver_sub_minor;
88*4c45a51eSXuan Zhuo 
89*4c45a51eSXuan Zhuo 	__le16	spec_ver_major;
90*4c45a51eSXuan Zhuo 	__le16	spec_ver_minor;
91*4c45a51eSXuan Zhuo 	__le16	pci_bdf;
92*4c45a51eSXuan Zhuo 	__le32	pci_domain;
93*4c45a51eSXuan Zhuo 
94*4c45a51eSXuan Zhuo 	u8      os_ver_str[64];
95*4c45a51eSXuan Zhuo 	u8      isa_str[64];
96*4c45a51eSXuan Zhuo };
97*4c45a51eSXuan Zhuo 
98*4c45a51eSXuan Zhuo #define EEA_HINFO_MAX_REP_LEN	1024
99*4c45a51eSXuan Zhuo #define EEA_HINFO_REP_BAD	2
100*4c45a51eSXuan Zhuo 
101*4c45a51eSXuan Zhuo struct eea_aq_host_info_rep {
102*4c45a51eSXuan Zhuo 	u8	op_code;
103*4c45a51eSXuan Zhuo 	u8	has_reply;
104*4c45a51eSXuan Zhuo 	u8	reply_str[EEA_HINFO_MAX_REP_LEN];
105*4c45a51eSXuan Zhuo };
106*4c45a51eSXuan Zhuo 
107*4c45a51eSXuan Zhuo static struct eea_ring *qid_to_ering(struct eea_net *enet, u32 qid)
108*4c45a51eSXuan Zhuo {
109*4c45a51eSXuan Zhuo 	struct eea_ring *ering;
110*4c45a51eSXuan Zhuo 
111*4c45a51eSXuan Zhuo 	if (qid % 2 == 0)
112*4c45a51eSXuan Zhuo 		ering = enet->rx[qid / 2]->ering;
113*4c45a51eSXuan Zhuo 	else
114*4c45a51eSXuan Zhuo 		ering = enet->tx[qid / 2].ering;
115*4c45a51eSXuan Zhuo 
116*4c45a51eSXuan Zhuo 	return ering;
117*4c45a51eSXuan Zhuo }
118*4c45a51eSXuan Zhuo 
119*4c45a51eSXuan Zhuo #define EEA_AQ_TIMEOUT_US (60 * 1000 * 1000)
120*4c45a51eSXuan Zhuo 
121*4c45a51eSXuan Zhuo static void eea_device_broken(struct eea_net *enet)
122*4c45a51eSXuan Zhuo {
123*4c45a51eSXuan Zhuo 	if (enet->adminq.broken)
124*4c45a51eSXuan Zhuo 		return;
125*4c45a51eSXuan Zhuo 
126*4c45a51eSXuan Zhuo 	eea_device_reset(enet->edev);
127*4c45a51eSXuan Zhuo 	enet->adminq.broken = true;
128*4c45a51eSXuan Zhuo }
129*4c45a51eSXuan Zhuo 
130*4c45a51eSXuan Zhuo static int eea_adminq_submit(struct eea_net *enet, u16 cmd,
131*4c45a51eSXuan Zhuo 			     dma_addr_t req_addr, dma_addr_t res_addr,
132*4c45a51eSXuan Zhuo 			     u32 req_size, u32 res_size, u32 *reply_len)
133*4c45a51eSXuan Zhuo {
134*4c45a51eSXuan Zhuo 	struct eea_aq_cdesc *cdesc;
135*4c45a51eSXuan Zhuo 	struct eea_aq_desc *desc;
136*4c45a51eSXuan Zhuo 	int ret;
137*4c45a51eSXuan Zhuo 
138*4c45a51eSXuan Zhuo 	if (enet->adminq.broken)
139*4c45a51eSXuan Zhuo 		return -EIO;
140*4c45a51eSXuan Zhuo 
141*4c45a51eSXuan Zhuo 	desc = eea_ering_aq_alloc_desc(enet->adminq.ring);
142*4c45a51eSXuan Zhuo 
143*4c45a51eSXuan Zhuo 	desc->classid = cmd >> 8;
144*4c45a51eSXuan Zhuo 	desc->command = cmd & 0xff;
145*4c45a51eSXuan Zhuo 
146*4c45a51eSXuan Zhuo 	desc->data_addr = cpu_to_le64(req_addr);
147*4c45a51eSXuan Zhuo 	desc->data_len = cpu_to_le32(req_size);
148*4c45a51eSXuan Zhuo 
149*4c45a51eSXuan Zhuo 	desc->reply_addr = cpu_to_le64(res_addr);
150*4c45a51eSXuan Zhuo 	desc->reply_len = cpu_to_le32(res_size);
151*4c45a51eSXuan Zhuo 
152*4c45a51eSXuan Zhuo 	/* for update flags */
153*4c45a51eSXuan Zhuo 	dma_wmb();
154*4c45a51eSXuan Zhuo 
155*4c45a51eSXuan Zhuo 	desc->flags = cpu_to_le16(enet->adminq.phase);
156*4c45a51eSXuan Zhuo 
157*4c45a51eSXuan Zhuo 	eea_ering_sq_commit_desc(enet->adminq.ring);
158*4c45a51eSXuan Zhuo 
159*4c45a51eSXuan Zhuo 	eea_ering_kick(enet->adminq.ring);
160*4c45a51eSXuan Zhuo 
161*4c45a51eSXuan Zhuo 	++enet->adminq.num;
162*4c45a51eSXuan Zhuo 
163*4c45a51eSXuan Zhuo 	if ((enet->adminq.num % enet->adminq.ring->num) == 0)
164*4c45a51eSXuan Zhuo 		enet->adminq.phase ^= EEA_RING_DESC_F_AQ_PHASE;
165*4c45a51eSXuan Zhuo 
166*4c45a51eSXuan Zhuo 	ret = read_poll_timeout(eea_ering_cq_get_desc, cdesc, cdesc, 10,
167*4c45a51eSXuan Zhuo 				EEA_AQ_TIMEOUT_US, false, enet->adminq.ring);
168*4c45a51eSXuan Zhuo 	if (ret) {
169*4c45a51eSXuan Zhuo 		netdev_err(enet->netdev,
170*4c45a51eSXuan Zhuo 			   "adminq exec timeout. cmd: %d reset device.\n",
171*4c45a51eSXuan Zhuo 			   cmd);
172*4c45a51eSXuan Zhuo 		/* The device must be reset before unmapping buffers to avoid
173*4c45a51eSXuan Zhuo 		 * potential DMA writes after the memory is freed.
174*4c45a51eSXuan Zhuo 		 */
175*4c45a51eSXuan Zhuo 		eea_device_broken(enet);
176*4c45a51eSXuan Zhuo 		return ret;
177*4c45a51eSXuan Zhuo 	}
178*4c45a51eSXuan Zhuo 
179*4c45a51eSXuan Zhuo 	/* Returns 0 on success, or a negative error code on failure. */
180*4c45a51eSXuan Zhuo 	ret = le32_to_cpu(cdesc->status);
181*4c45a51eSXuan Zhuo 
182*4c45a51eSXuan Zhuo 	eea_ering_cq_ack_desc(enet->adminq.ring, 1);
183*4c45a51eSXuan Zhuo 
184*4c45a51eSXuan Zhuo 	if (ret)
185*4c45a51eSXuan Zhuo 		netdev_err(enet->netdev,
186*4c45a51eSXuan Zhuo 			   "adminq exec failed. cmd: %d ret %d\n", cmd, ret);
187*4c45a51eSXuan Zhuo 	else
188*4c45a51eSXuan Zhuo 		*reply_len = le32_to_cpu(cdesc->reply_len);
189*4c45a51eSXuan Zhuo 
190*4c45a51eSXuan Zhuo 	return ret;
191*4c45a51eSXuan Zhuo }
192*4c45a51eSXuan Zhuo 
193*4c45a51eSXuan Zhuo static int eea_adminq_exec(struct eea_net *enet, u16 cmd,
194*4c45a51eSXuan Zhuo 			   void *req, u32 req_size,
195*4c45a51eSXuan Zhuo 			   void *res, u32 res_size,
196*4c45a51eSXuan Zhuo 			   u32 *reply)
197*4c45a51eSXuan Zhuo {
198*4c45a51eSXuan Zhuo 	dma_addr_t req_addr = 0, res_addr = 0;
199*4c45a51eSXuan Zhuo 	struct device *dma;
200*4c45a51eSXuan Zhuo 	u32 reply_len = 0;
201*4c45a51eSXuan Zhuo 	int ret;
202*4c45a51eSXuan Zhuo 
203*4c45a51eSXuan Zhuo 	if (reply)
204*4c45a51eSXuan Zhuo 		*reply = 0;
205*4c45a51eSXuan Zhuo 
206*4c45a51eSXuan Zhuo 	dma = enet->edev->dma_dev;
207*4c45a51eSXuan Zhuo 
208*4c45a51eSXuan Zhuo 	if (req) {
209*4c45a51eSXuan Zhuo 		req_addr = dma_map_single(dma, req, req_size, DMA_TO_DEVICE);
210*4c45a51eSXuan Zhuo 		if (unlikely(dma_mapping_error(dma, req_addr)))
211*4c45a51eSXuan Zhuo 			return -ENOMEM;
212*4c45a51eSXuan Zhuo 	}
213*4c45a51eSXuan Zhuo 
214*4c45a51eSXuan Zhuo 	if (res) {
215*4c45a51eSXuan Zhuo 		res_addr = dma_map_single(dma, res, res_size, DMA_FROM_DEVICE);
216*4c45a51eSXuan Zhuo 		if (unlikely(dma_mapping_error(dma, res_addr))) {
217*4c45a51eSXuan Zhuo 			ret = -ENOMEM;
218*4c45a51eSXuan Zhuo 			goto err_unmap_req;
219*4c45a51eSXuan Zhuo 		}
220*4c45a51eSXuan Zhuo 	}
221*4c45a51eSXuan Zhuo 
222*4c45a51eSXuan Zhuo 	mutex_lock(&enet->adminq.lock);
223*4c45a51eSXuan Zhuo 	ret = eea_adminq_submit(enet, cmd, req_addr, res_addr,
224*4c45a51eSXuan Zhuo 				req_size, res_size, &reply_len);
225*4c45a51eSXuan Zhuo 	mutex_unlock(&enet->adminq.lock);
226*4c45a51eSXuan Zhuo 	if (res) {
227*4c45a51eSXuan Zhuo 		dma_unmap_single(dma, res_addr, res_size, DMA_FROM_DEVICE);
228*4c45a51eSXuan Zhuo 
229*4c45a51eSXuan Zhuo 		if (ret)
230*4c45a51eSXuan Zhuo 			memset(res, 0, res_size);
231*4c45a51eSXuan Zhuo 		else if (res_size > reply_len)
232*4c45a51eSXuan Zhuo 			memset(res + reply_len, 0, res_size - reply_len);
233*4c45a51eSXuan Zhuo 
234*4c45a51eSXuan Zhuo 		if (reply)
235*4c45a51eSXuan Zhuo 			*reply = reply_len;
236*4c45a51eSXuan Zhuo 	}
237*4c45a51eSXuan Zhuo 
238*4c45a51eSXuan Zhuo err_unmap_req:
239*4c45a51eSXuan Zhuo 	if (req)
240*4c45a51eSXuan Zhuo 		dma_unmap_single(dma, req_addr, req_size, DMA_TO_DEVICE);
241*4c45a51eSXuan Zhuo 
242*4c45a51eSXuan Zhuo 	return ret;
243*4c45a51eSXuan Zhuo }
244*4c45a51eSXuan Zhuo 
245*4c45a51eSXuan Zhuo void eea_destroy_adminq(struct eea_net *enet)
246*4c45a51eSXuan Zhuo {
247*4c45a51eSXuan Zhuo 	struct eea_aq *aq;
248*4c45a51eSXuan Zhuo 
249*4c45a51eSXuan Zhuo 	aq = &enet->adminq;
250*4c45a51eSXuan Zhuo 
251*4c45a51eSXuan Zhuo 	if (aq->ring) {
252*4c45a51eSXuan Zhuo 		eea_ering_free(aq->ring);
253*4c45a51eSXuan Zhuo 		aq->ring = NULL;
254*4c45a51eSXuan Zhuo 		aq->phase = 0;
255*4c45a51eSXuan Zhuo 	}
256*4c45a51eSXuan Zhuo 
257*4c45a51eSXuan Zhuo 	kfree(aq->q_req_buf);
258*4c45a51eSXuan Zhuo 	kfree(aq->q_res_buf);
259*4c45a51eSXuan Zhuo 
260*4c45a51eSXuan Zhuo 	aq->q_req_buf = NULL;
261*4c45a51eSXuan Zhuo 	aq->q_res_buf = NULL;
262*4c45a51eSXuan Zhuo }
263*4c45a51eSXuan Zhuo 
264*4c45a51eSXuan Zhuo int eea_create_adminq(struct eea_net *enet, u32 qid)
265*4c45a51eSXuan Zhuo {
266*4c45a51eSXuan Zhuo 	u32 db_size, q_size, num;
267*4c45a51eSXuan Zhuo 	struct eea_ring *ering;
268*4c45a51eSXuan Zhuo 	struct eea_aq *aq;
269*4c45a51eSXuan Zhuo 	int err = -ENOMEM;
270*4c45a51eSXuan Zhuo 
271*4c45a51eSXuan Zhuo 	num = enet->edev->rx_num + enet->edev->tx_num;
272*4c45a51eSXuan Zhuo 	aq = &enet->adminq;
273*4c45a51eSXuan Zhuo 
274*4c45a51eSXuan Zhuo 	ering = eea_ering_alloc(qid, 64, enet->edev, sizeof(struct eea_aq_desc),
275*4c45a51eSXuan Zhuo 				sizeof(struct eea_aq_cdesc), "adminq");
276*4c45a51eSXuan Zhuo 	if (!ering)
277*4c45a51eSXuan Zhuo 		return -ENOMEM;
278*4c45a51eSXuan Zhuo 
279*4c45a51eSXuan Zhuo 	aq->ring = ering;
280*4c45a51eSXuan Zhuo 
281*4c45a51eSXuan Zhuo 	err = eea_pci_active_aq(ering, qid / 2 + 1);
282*4c45a51eSXuan Zhuo 	if (err)
283*4c45a51eSXuan Zhuo 		goto err;
284*4c45a51eSXuan Zhuo 
285*4c45a51eSXuan Zhuo 	aq->phase = BIT(7);
286*4c45a51eSXuan Zhuo 	aq->num = 0;
287*4c45a51eSXuan Zhuo 
288*4c45a51eSXuan Zhuo 	q_size = sizeof(*aq->q_req_buf) * num;
289*4c45a51eSXuan Zhuo 	db_size = sizeof(*aq->q_res_buf) * num;
290*4c45a51eSXuan Zhuo 
291*4c45a51eSXuan Zhuo 	aq->q_req_size = q_size;
292*4c45a51eSXuan Zhuo 	aq->q_res_size = db_size;
293*4c45a51eSXuan Zhuo 
294*4c45a51eSXuan Zhuo 	err = -ENOMEM;
295*4c45a51eSXuan Zhuo 
296*4c45a51eSXuan Zhuo 	aq->q_req_buf = kzalloc(q_size, GFP_KERNEL);
297*4c45a51eSXuan Zhuo 	if (!aq->q_req_buf)
298*4c45a51eSXuan Zhuo 		goto err;
299*4c45a51eSXuan Zhuo 
300*4c45a51eSXuan Zhuo 	aq->q_res_buf = kzalloc(db_size, GFP_KERNEL);
301*4c45a51eSXuan Zhuo 	if (!aq->q_res_buf)
302*4c45a51eSXuan Zhuo 		goto err;
303*4c45a51eSXuan Zhuo 
304*4c45a51eSXuan Zhuo 	/* Before we set up the AQ, the device remains in an inactive state, so
305*4c45a51eSXuan Zhuo 	 * there will be no DMA operations. If the 'set up AQ' process fails, we
306*4c45a51eSXuan Zhuo 	 * can safely free the DMA-related memory.
307*4c45a51eSXuan Zhuo 	 */
308*4c45a51eSXuan Zhuo 	err = eea_pci_set_aq_up(enet->edev);
309*4c45a51eSXuan Zhuo 	if (err)
310*4c45a51eSXuan Zhuo 		goto err;
311*4c45a51eSXuan Zhuo 
312*4c45a51eSXuan Zhuo 	aq->broken = false;
313*4c45a51eSXuan Zhuo 
314*4c45a51eSXuan Zhuo 	mutex_init(&aq->lock);
315*4c45a51eSXuan Zhuo 
316*4c45a51eSXuan Zhuo 	return 0;
317*4c45a51eSXuan Zhuo 
318*4c45a51eSXuan Zhuo err:
319*4c45a51eSXuan Zhuo 	eea_destroy_adminq(enet);
320*4c45a51eSXuan Zhuo 	return err;
321*4c45a51eSXuan Zhuo }
322*4c45a51eSXuan Zhuo 
323*4c45a51eSXuan Zhuo int eea_adminq_query_cfg(struct eea_net *enet, struct eea_aq_cfg *cfg)
324*4c45a51eSXuan Zhuo {
325*4c45a51eSXuan Zhuo 	return eea_adminq_exec(enet, EEA_AQ_CMD_CFG_QUERY, NULL, 0, cfg,
326*4c45a51eSXuan Zhuo 			       sizeof(*cfg), NULL);
327*4c45a51eSXuan Zhuo }
328*4c45a51eSXuan Zhuo 
329*4c45a51eSXuan Zhuo static void qcfg_fill(struct eea_aq_create *qcfg, struct eea_ring *ering,
330*4c45a51eSXuan Zhuo 		      u32 flags)
331*4c45a51eSXuan Zhuo {
332*4c45a51eSXuan Zhuo 	qcfg->flags = cpu_to_le32(flags);
333*4c45a51eSXuan Zhuo 	qcfg->qidx = cpu_to_le16(ering->index);
334*4c45a51eSXuan Zhuo 	qcfg->depth = cpu_to_le16(ering->num);
335*4c45a51eSXuan Zhuo 
336*4c45a51eSXuan Zhuo 	qcfg->hdr_buf_size = flags & EEA_QUEUE_FLAGS_HW_SPLIT_HDR ? 1 : 0;
337*4c45a51eSXuan Zhuo 	qcfg->sq_desc_size = ering->sq.desc_size;
338*4c45a51eSXuan Zhuo 	qcfg->cq_desc_size = ering->cq.desc_size;
339*4c45a51eSXuan Zhuo 	qcfg->msix_vector = cpu_to_le16(ering->msix_vec);
340*4c45a51eSXuan Zhuo 
341*4c45a51eSXuan Zhuo 	qcfg->sq_addr_low = cpu_to_le32(lower_32_bits(ering->sq.dma_addr));
342*4c45a51eSXuan Zhuo 	qcfg->sq_addr_high = cpu_to_le32(upper_32_bits(ering->sq.dma_addr));
343*4c45a51eSXuan Zhuo 
344*4c45a51eSXuan Zhuo 	qcfg->cq_addr_low = cpu_to_le32(lower_32_bits(ering->cq.dma_addr));
345*4c45a51eSXuan Zhuo 	qcfg->cq_addr_high = cpu_to_le32(upper_32_bits(ering->cq.dma_addr));
346*4c45a51eSXuan Zhuo }
347*4c45a51eSXuan Zhuo 
348*4c45a51eSXuan Zhuo int eea_adminq_create_q(struct eea_net *enet, u32 num, u32 flags)
349*4c45a51eSXuan Zhuo {
350*4c45a51eSXuan Zhuo 	int i, db_size, q_size, err = -ENOMEM;
351*4c45a51eSXuan Zhuo 	struct eea_net_cfg *cfg;
352*4c45a51eSXuan Zhuo 	struct eea_ring *ering;
353*4c45a51eSXuan Zhuo 	struct eea_aq *aq;
354*4c45a51eSXuan Zhuo 	u32 reply_len;
355*4c45a51eSXuan Zhuo 
356*4c45a51eSXuan Zhuo 	cfg = &enet->cfg;
357*4c45a51eSXuan Zhuo 	aq = &enet->adminq;
358*4c45a51eSXuan Zhuo 
359*4c45a51eSXuan Zhuo 	if (cfg->split_hdr)
360*4c45a51eSXuan Zhuo 		flags |= EEA_QUEUE_FLAGS_HW_SPLIT_HDR;
361*4c45a51eSXuan Zhuo 
362*4c45a51eSXuan Zhuo 	flags |= EEA_QUEUE_FLAGS_SQCQ;
363*4c45a51eSXuan Zhuo 	flags |= EEA_QUEUE_FLAGS_HWTS;
364*4c45a51eSXuan Zhuo 
365*4c45a51eSXuan Zhuo 	q_size = sizeof(*aq->q_req_buf) * num;
366*4c45a51eSXuan Zhuo 	db_size = sizeof(*aq->q_res_buf) * num;
367*4c45a51eSXuan Zhuo 
368*4c45a51eSXuan Zhuo 	for (i = 0; i < num; i++) {
369*4c45a51eSXuan Zhuo 		ering = qid_to_ering(enet, i);
370*4c45a51eSXuan Zhuo 		qcfg_fill(aq->q_req_buf + i, ering, flags);
371*4c45a51eSXuan Zhuo 	}
372*4c45a51eSXuan Zhuo 
373*4c45a51eSXuan Zhuo 	err = eea_adminq_exec(enet, EEA_AQ_CMD_QUEUE_CREATE,
374*4c45a51eSXuan Zhuo 			      aq->q_req_buf, q_size,
375*4c45a51eSXuan Zhuo 			      aq->q_res_buf, db_size,
376*4c45a51eSXuan Zhuo 			      &reply_len);
377*4c45a51eSXuan Zhuo 	if (err)
378*4c45a51eSXuan Zhuo 		return err;
379*4c45a51eSXuan Zhuo 
380*4c45a51eSXuan Zhuo 	if (reply_len != db_size) {
381*4c45a51eSXuan Zhuo 		eea_adminq_destroy_all_q(enet);
382*4c45a51eSXuan Zhuo 		netdev_err(enet->netdev, "invalid reply len %u\n", reply_len);
383*4c45a51eSXuan Zhuo 		return -EINVAL;
384*4c45a51eSXuan Zhuo 	}
385*4c45a51eSXuan Zhuo 
386*4c45a51eSXuan Zhuo 	for (i = 0; i < num; i++) {
387*4c45a51eSXuan Zhuo 		ering = qid_to_ering(enet, i);
388*4c45a51eSXuan Zhuo 		ering->db = eea_pci_db_addr(ering->edev,
389*4c45a51eSXuan Zhuo 					    le32_to_cpu(aq->q_res_buf[i]));
390*4c45a51eSXuan Zhuo 		if (!ering->db) {
391*4c45a51eSXuan Zhuo 			netdev_err(enet->netdev, "invalid db off %u\n",
392*4c45a51eSXuan Zhuo 				   le32_to_cpu(aq->q_res_buf[i]));
393*4c45a51eSXuan Zhuo 			goto err;
394*4c45a51eSXuan Zhuo 		}
395*4c45a51eSXuan Zhuo 	}
396*4c45a51eSXuan Zhuo 
397*4c45a51eSXuan Zhuo 	return err;
398*4c45a51eSXuan Zhuo 
399*4c45a51eSXuan Zhuo err:
400*4c45a51eSXuan Zhuo 	eea_adminq_destroy_all_q(enet);
401*4c45a51eSXuan Zhuo 	for (i = 0; i < num; i++) {
402*4c45a51eSXuan Zhuo 		ering = qid_to_ering(enet, i);
403*4c45a51eSXuan Zhuo 		ering->db = NULL;
404*4c45a51eSXuan Zhuo 	}
405*4c45a51eSXuan Zhuo 
406*4c45a51eSXuan Zhuo 	return -EIO;
407*4c45a51eSXuan Zhuo }
408*4c45a51eSXuan Zhuo 
409*4c45a51eSXuan Zhuo int eea_adminq_destroy_all_q(struct eea_net *enet)
410*4c45a51eSXuan Zhuo {
411*4c45a51eSXuan Zhuo 	int err;
412*4c45a51eSXuan Zhuo 
413*4c45a51eSXuan Zhuo 	err = eea_adminq_exec(enet, EEA_AQ_CMD_QUEUE_DESTROY_ALL, NULL, 0,
414*4c45a51eSXuan Zhuo 			      NULL, 0, NULL);
415*4c45a51eSXuan Zhuo 	if (err) {
416*4c45a51eSXuan Zhuo 		/* The device must be reset before unmapping buffers to avoid
417*4c45a51eSXuan Zhuo 		 * potential DMA writes after the memory is freed.
418*4c45a51eSXuan Zhuo 		 */
419*4c45a51eSXuan Zhuo 		mutex_lock(&enet->adminq.lock);
420*4c45a51eSXuan Zhuo 		eea_device_broken(enet);
421*4c45a51eSXuan Zhuo 		mutex_unlock(&enet->adminq.lock);
422*4c45a51eSXuan Zhuo 
423*4c45a51eSXuan Zhuo 		netdev_err(enet->netdev, "QUEUE_DESTROY fail: reset device.\n");
424*4c45a51eSXuan Zhuo 	}
425*4c45a51eSXuan Zhuo 
426*4c45a51eSXuan Zhuo 	return err;
427*4c45a51eSXuan Zhuo }
428*4c45a51eSXuan Zhuo 
429*4c45a51eSXuan Zhuo /* The caller must ensure that both the 'rx' and 'tx' arrays are valid. */
430*4c45a51eSXuan Zhuo int eea_adminq_dev_status(struct eea_net *enet,
431*4c45a51eSXuan Zhuo 			  struct eea_aq_dev_status *dstatus)
432*4c45a51eSXuan Zhuo {
433*4c45a51eSXuan Zhuo 	struct eea_aq_queue_drv_status *drv_status;
434*4c45a51eSXuan Zhuo 	struct __eea_aq_dev_status *dev_status;
435*4c45a51eSXuan Zhuo 	int err, i, io_num, size, q_num;
436*4c45a51eSXuan Zhuo 	struct eea_ring *ering;
437*4c45a51eSXuan Zhuo 	void *rep, *req;
438*4c45a51eSXuan Zhuo 
439*4c45a51eSXuan Zhuo 	q_num = enet->cfg.rx_ring_num + enet->cfg.tx_ring_num + 1;
440*4c45a51eSXuan Zhuo 	io_num = enet->cfg.rx_ring_num + enet->cfg.tx_ring_num;
441*4c45a51eSXuan Zhuo 
442*4c45a51eSXuan Zhuo 	req = kcalloc(q_num, sizeof(struct eea_aq_queue_drv_status),
443*4c45a51eSXuan Zhuo 		      GFP_KERNEL);
444*4c45a51eSXuan Zhuo 	if (!req)
445*4c45a51eSXuan Zhuo 		return -ENOMEM;
446*4c45a51eSXuan Zhuo 
447*4c45a51eSXuan Zhuo 	size = struct_size(dev_status, q_status, q_num);
448*4c45a51eSXuan Zhuo 
449*4c45a51eSXuan Zhuo 	rep = kzalloc(size, GFP_KERNEL);
450*4c45a51eSXuan Zhuo 	if (!rep) {
451*4c45a51eSXuan Zhuo 		kfree(req);
452*4c45a51eSXuan Zhuo 		return -ENOMEM;
453*4c45a51eSXuan Zhuo 	}
454*4c45a51eSXuan Zhuo 
455*4c45a51eSXuan Zhuo 	drv_status = req;
456*4c45a51eSXuan Zhuo 	for (i = 0; i < io_num; ++i, ++drv_status) {
457*4c45a51eSXuan Zhuo 		ering = qid_to_ering(enet, i);
458*4c45a51eSXuan Zhuo 		drv_status->qidx = cpu_to_le16(i);
459*4c45a51eSXuan Zhuo 		drv_status->cq_head = cpu_to_le16(ering->cq.head);
460*4c45a51eSXuan Zhuo 		drv_status->sq_head = cpu_to_le16(ering->sq.head);
461*4c45a51eSXuan Zhuo 	}
462*4c45a51eSXuan Zhuo 
463*4c45a51eSXuan Zhuo 	drv_status->qidx = cpu_to_le16(i);
464*4c45a51eSXuan Zhuo 	drv_status->cq_head = cpu_to_le16(enet->adminq.ring->cq.head);
465*4c45a51eSXuan Zhuo 	drv_status->sq_head = cpu_to_le16(enet->adminq.ring->sq.head);
466*4c45a51eSXuan Zhuo 
467*4c45a51eSXuan Zhuo 	err = eea_adminq_exec(enet, EEA_AQ_CMD_DEV_STATUS, req,
468*4c45a51eSXuan Zhuo 			      q_num * sizeof(struct eea_aq_queue_drv_status),
469*4c45a51eSXuan Zhuo 			      rep, size, NULL);
470*4c45a51eSXuan Zhuo 	kfree(req);
471*4c45a51eSXuan Zhuo 	if (err) {
472*4c45a51eSXuan Zhuo 		kfree(rep);
473*4c45a51eSXuan Zhuo 		return err;
474*4c45a51eSXuan Zhuo 	}
475*4c45a51eSXuan Zhuo 
476*4c45a51eSXuan Zhuo 	dstatus->num = q_num;
477*4c45a51eSXuan Zhuo 	dstatus->status = rep;
478*4c45a51eSXuan Zhuo 
479*4c45a51eSXuan Zhuo 	return 0;
480*4c45a51eSXuan Zhuo }
481*4c45a51eSXuan Zhuo 
482*4c45a51eSXuan Zhuo void eea_adminq_config_host_info(struct eea_net *enet)
483*4c45a51eSXuan Zhuo {
484*4c45a51eSXuan Zhuo 	struct device *dev = enet->edev->dma_dev;
485*4c45a51eSXuan Zhuo 	struct eea_aq_host_info_cfg *cfg;
486*4c45a51eSXuan Zhuo 	struct eea_aq_host_info_rep *rep;
487*4c45a51eSXuan Zhuo 	int rc = -ENOMEM;
488*4c45a51eSXuan Zhuo 
489*4c45a51eSXuan Zhuo 	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
490*4c45a51eSXuan Zhuo 	if (!cfg)
491*4c45a51eSXuan Zhuo 		return;
492*4c45a51eSXuan Zhuo 
493*4c45a51eSXuan Zhuo 	rep = kzalloc(sizeof(*rep), GFP_KERNEL);
494*4c45a51eSXuan Zhuo 	if (!rep)
495*4c45a51eSXuan Zhuo 		goto err_free_cfg;
496*4c45a51eSXuan Zhuo 
497*4c45a51eSXuan Zhuo 	cfg->os_type            = cpu_to_le16(EEA_OS_LINUX);
498*4c45a51eSXuan Zhuo 	cfg->os_dist            = cpu_to_le16(EEA_OS_DISTRO);
499*4c45a51eSXuan Zhuo 	cfg->drv_type           = cpu_to_le16(EEA_DRV_TYPE);
500*4c45a51eSXuan Zhuo 
501*4c45a51eSXuan Zhuo 	cfg->kern_ver_major     = cpu_to_le16(LINUX_VERSION_MAJOR);
502*4c45a51eSXuan Zhuo 	cfg->kern_ver_minor     = cpu_to_le16(LINUX_VERSION_PATCHLEVEL);
503*4c45a51eSXuan Zhuo 	cfg->kern_ver_sub_minor = cpu_to_le16(LINUX_VERSION_SUBLEVEL);
504*4c45a51eSXuan Zhuo 
505*4c45a51eSXuan Zhuo 	cfg->drv_ver_major      = cpu_to_le16(EEA_VER_MAJOR);
506*4c45a51eSXuan Zhuo 	cfg->drv_ver_minor      = cpu_to_le16(EEA_VER_MINOR);
507*4c45a51eSXuan Zhuo 	cfg->drv_ver_sub_minor  = cpu_to_le16(EEA_VER_SUB_MINOR);
508*4c45a51eSXuan Zhuo 
509*4c45a51eSXuan Zhuo 	cfg->spec_ver_major     = cpu_to_le16(EEA_SPEC_VER_MAJOR);
510*4c45a51eSXuan Zhuo 	cfg->spec_ver_minor     = cpu_to_le16(EEA_SPEC_VER_MINOR);
511*4c45a51eSXuan Zhuo 
512*4c45a51eSXuan Zhuo 	cfg->pci_bdf            = cpu_to_le16(eea_pci_bdf(enet->edev));
513*4c45a51eSXuan Zhuo 	cfg->pci_domain         = cpu_to_le32(eea_pci_domain_nr(enet->edev));
514*4c45a51eSXuan Zhuo 
515*4c45a51eSXuan Zhuo 	strscpy(cfg->os_ver_str, utsname()->release, sizeof(cfg->os_ver_str));
516*4c45a51eSXuan Zhuo 	strscpy(cfg->isa_str, utsname()->machine, sizeof(cfg->isa_str));
517*4c45a51eSXuan Zhuo 
518*4c45a51eSXuan Zhuo 	rc = eea_adminq_exec(enet, EEA_AQ_CMD_HOST_INFO,
519*4c45a51eSXuan Zhuo 			     cfg, sizeof(*cfg), rep, sizeof(*rep), NULL);
520*4c45a51eSXuan Zhuo 
521*4c45a51eSXuan Zhuo 	if (!rc) {
522*4c45a51eSXuan Zhuo 		if (rep->op_code == EEA_HINFO_REP_BAD)
523*4c45a51eSXuan Zhuo 			dev_warn(dev, "The hardware-driven state validation may be abnormal.\n");
524*4c45a51eSXuan Zhuo 
525*4c45a51eSXuan Zhuo 		if (rep->has_reply) {
526*4c45a51eSXuan Zhuo 			char buf[EEA_HINFO_MAX_REP_LEN] = {0};
527*4c45a51eSXuan Zhuo 
528*4c45a51eSXuan Zhuo 			rep->reply_str[EEA_HINFO_MAX_REP_LEN - 1] = '\0';
529*4c45a51eSXuan Zhuo 
530*4c45a51eSXuan Zhuo 			string_escape_str(rep->reply_str, buf, sizeof(buf),
531*4c45a51eSXuan Zhuo 					  ESCAPE_NP, NULL);
532*4c45a51eSXuan Zhuo 
533*4c45a51eSXuan Zhuo 			buf[EEA_HINFO_MAX_REP_LEN - 1] = '\0';
534*4c45a51eSXuan Zhuo 
535*4c45a51eSXuan Zhuo 			dev_warn(dev, "Device replied: %s\n", buf);
536*4c45a51eSXuan Zhuo 		}
537*4c45a51eSXuan Zhuo 	}
538*4c45a51eSXuan Zhuo 
539*4c45a51eSXuan Zhuo 	kfree(rep);
540*4c45a51eSXuan Zhuo err_free_cfg:
541*4c45a51eSXuan Zhuo 	kfree(cfg);
542*4c45a51eSXuan Zhuo }
543