Skip to content

Commit a04ff73

Browse files
xavierhwdledford
authored andcommitted
RDMA/hns: Add command queue support for hip08 RoCE driver
The command queue is the configuration queue. The software configures hardware by filling the commands into command queues. It includes command send queue and receive queue. In hip08 RoCE engine, It supports to configure and query registers by command queue. Signed-off-by: Lijun Ou <[email protected]> Signed-off-by: Shaobo Xu <[email protected]> Signed-off-by: Wei Hu (Xavier) <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 13ca970 commit a04ff73

File tree

5 files changed

+420
-1
lines changed

5 files changed

+420
-1
lines changed

drivers/infiniband/hw/hns/hns_roce_common.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,4 +362,17 @@
362362
#define ROCEE_ECC_UCERR_ALM0_REG 0xB34
363363
#define ROCEE_ECC_CERR_ALM0_REG 0xB40
364364

365+
/* V2 ROCEE REG */
366+
#define ROCEE_TX_CMQ_BASEADDR_L_REG 0x07000
367+
#define ROCEE_TX_CMQ_BASEADDR_H_REG 0x07004
368+
#define ROCEE_TX_CMQ_DEPTH_REG 0x07008
369+
#define ROCEE_TX_CMQ_TAIL_REG 0x07010
370+
#define ROCEE_TX_CMQ_HEAD_REG 0x07014
371+
372+
#define ROCEE_RX_CMQ_BASEADDR_L_REG 0x07018
373+
#define ROCEE_RX_CMQ_BASEADDR_H_REG 0x0701c
374+
#define ROCEE_RX_CMQ_DEPTH_REG 0x07020
375+
#define ROCEE_RX_CMQ_TAIL_REG 0x07024
376+
#define ROCEE_RX_CMQ_HEAD_REG 0x07028
377+
365378
#endif /* _HNS_ROCE_COMMON_H */

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,8 @@ struct hns_roce_caps {
506506

507507
struct hns_roce_hw {
508508
int (*reset)(struct hns_roce_dev *hr_dev, bool enable);
509+
int (*cmq_init)(struct hns_roce_dev *hr_dev);
510+
void (*cmq_exit)(struct hns_roce_dev *hr_dev);
509511
void (*hw_profile)(struct hns_roce_dev *hr_dev);
510512
int (*hw_init)(struct hns_roce_dev *hr_dev);
511513
void (*hw_exit)(struct hns_roce_dev *hr_dev);

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 280 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,277 @@
4141
#include "hns_roce_device.h"
4242
#include "hns_roce_cmd.h"
4343
#include "hns_roce_hem.h"
44+
#include "hns_roce_hw_v2.h"
4445

45-
static const struct hns_roce_hw hns_roce_hw_v2;
46+
static int hns_roce_cmq_space(struct hns_roce_v2_cmq_ring *ring)
47+
{
48+
int ntu = ring->next_to_use;
49+
int ntc = ring->next_to_clean;
50+
int used = (ntu - ntc + ring->desc_num) % ring->desc_num;
51+
52+
return ring->desc_num - used - 1;
53+
}
54+
55+
static int hns_roce_alloc_cmq_desc(struct hns_roce_dev *hr_dev,
56+
struct hns_roce_v2_cmq_ring *ring)
57+
{
58+
int size = ring->desc_num * sizeof(struct hns_roce_cmq_desc);
59+
60+
ring->desc = kzalloc(size, GFP_KERNEL);
61+
if (!ring->desc)
62+
return -ENOMEM;
63+
64+
ring->desc_dma_addr = dma_map_single(hr_dev->dev, ring->desc, size,
65+
DMA_BIDIRECTIONAL);
66+
if (dma_mapping_error(hr_dev->dev, ring->desc_dma_addr)) {
67+
ring->desc_dma_addr = 0;
68+
kfree(ring->desc);
69+
ring->desc = NULL;
70+
return -ENOMEM;
71+
}
72+
73+
return 0;
74+
}
75+
76+
static void hns_roce_free_cmq_desc(struct hns_roce_dev *hr_dev,
77+
struct hns_roce_v2_cmq_ring *ring)
78+
{
79+
dma_unmap_single(hr_dev->dev, ring->desc_dma_addr,
80+
ring->desc_num * sizeof(struct hns_roce_cmq_desc),
81+
DMA_BIDIRECTIONAL);
82+
kfree(ring->desc);
83+
}
84+
85+
static int hns_roce_init_cmq_ring(struct hns_roce_dev *hr_dev, bool ring_type)
86+
{
87+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
88+
struct hns_roce_v2_cmq_ring *ring = (ring_type == TYPE_CSQ) ?
89+
&priv->cmq.csq : &priv->cmq.crq;
90+
91+
ring->flag = ring_type;
92+
ring->next_to_clean = 0;
93+
ring->next_to_use = 0;
94+
95+
return hns_roce_alloc_cmq_desc(hr_dev, ring);
96+
}
97+
98+
static void hns_roce_cmq_init_regs(struct hns_roce_dev *hr_dev, bool ring_type)
99+
{
100+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
101+
struct hns_roce_v2_cmq_ring *ring = (ring_type == TYPE_CSQ) ?
102+
&priv->cmq.csq : &priv->cmq.crq;
103+
dma_addr_t dma = ring->desc_dma_addr;
104+
105+
if (ring_type == TYPE_CSQ) {
106+
roce_write(hr_dev, ROCEE_TX_CMQ_BASEADDR_L_REG, (u32)dma);
107+
roce_write(hr_dev, ROCEE_TX_CMQ_BASEADDR_H_REG,
108+
upper_32_bits(dma));
109+
roce_write(hr_dev, ROCEE_TX_CMQ_DEPTH_REG,
110+
(ring->desc_num >> HNS_ROCE_CMQ_DESC_NUM_S) |
111+
HNS_ROCE_CMQ_ENABLE);
112+
roce_write(hr_dev, ROCEE_TX_CMQ_HEAD_REG, 0);
113+
roce_write(hr_dev, ROCEE_TX_CMQ_TAIL_REG, 0);
114+
} else {
115+
roce_write(hr_dev, ROCEE_RX_CMQ_BASEADDR_L_REG, (u32)dma);
116+
roce_write(hr_dev, ROCEE_RX_CMQ_BASEADDR_H_REG,
117+
upper_32_bits(dma));
118+
roce_write(hr_dev, ROCEE_RX_CMQ_DEPTH_REG,
119+
(ring->desc_num >> HNS_ROCE_CMQ_DESC_NUM_S) |
120+
HNS_ROCE_CMQ_ENABLE);
121+
roce_write(hr_dev, ROCEE_RX_CMQ_HEAD_REG, 0);
122+
roce_write(hr_dev, ROCEE_RX_CMQ_TAIL_REG, 0);
123+
}
124+
}
125+
126+
static int hns_roce_v2_cmq_init(struct hns_roce_dev *hr_dev)
127+
{
128+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
129+
int ret;
130+
131+
/* Setup the queue entries for command queue */
132+
priv->cmq.csq.desc_num = 1024;
133+
priv->cmq.crq.desc_num = 1024;
134+
135+
/* Setup the lock for command queue */
136+
spin_lock_init(&priv->cmq.csq.lock);
137+
spin_lock_init(&priv->cmq.crq.lock);
138+
139+
/* Setup Tx write back timeout */
140+
priv->cmq.tx_timeout = HNS_ROCE_CMQ_TX_TIMEOUT;
141+
142+
/* Init CSQ */
143+
ret = hns_roce_init_cmq_ring(hr_dev, TYPE_CSQ);
144+
if (ret) {
145+
dev_err(hr_dev->dev, "Init CSQ error, ret = %d.\n", ret);
146+
return ret;
147+
}
148+
149+
/* Init CRQ */
150+
ret = hns_roce_init_cmq_ring(hr_dev, TYPE_CRQ);
151+
if (ret) {
152+
dev_err(hr_dev->dev, "Init CRQ error, ret = %d.\n", ret);
153+
goto err_crq;
154+
}
155+
156+
/* Init CSQ REG */
157+
hns_roce_cmq_init_regs(hr_dev, TYPE_CSQ);
158+
159+
/* Init CRQ REG */
160+
hns_roce_cmq_init_regs(hr_dev, TYPE_CRQ);
161+
162+
return 0;
163+
164+
err_crq:
165+
hns_roce_free_cmq_desc(hr_dev, &priv->cmq.csq);
166+
167+
return ret;
168+
}
169+
170+
static void hns_roce_v2_cmq_exit(struct hns_roce_dev *hr_dev)
171+
{
172+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
173+
174+
hns_roce_free_cmq_desc(hr_dev, &priv->cmq.csq);
175+
hns_roce_free_cmq_desc(hr_dev, &priv->cmq.crq);
176+
}
177+
178+
void hns_roce_cmq_setup_basic_desc(struct hns_roce_cmq_desc *desc,
179+
enum hns_roce_opcode_type opcode,
180+
bool is_read)
181+
{
182+
memset((void *)desc, 0, sizeof(struct hns_roce_cmq_desc));
183+
desc->opcode = cpu_to_le16(opcode);
184+
desc->flag =
185+
cpu_to_le16(HNS_ROCE_CMD_FLAG_NO_INTR | HNS_ROCE_CMD_FLAG_IN);
186+
if (is_read)
187+
desc->flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_WR);
188+
else
189+
desc->flag &= cpu_to_le16(~HNS_ROCE_CMD_FLAG_WR);
190+
}
191+
192+
static int hns_roce_cmq_csq_done(struct hns_roce_dev *hr_dev)
193+
{
194+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
195+
u32 head = roce_read(hr_dev, ROCEE_TX_CMQ_HEAD_REG);
196+
197+
return head == priv->cmq.csq.next_to_use;
198+
}
199+
200+
static int hns_roce_cmq_csq_clean(struct hns_roce_dev *hr_dev)
201+
{
202+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
203+
struct hns_roce_v2_cmq_ring *csq = &priv->cmq.csq;
204+
struct hns_roce_cmq_desc *desc;
205+
u16 ntc = csq->next_to_clean;
206+
u32 head;
207+
int clean = 0;
208+
209+
desc = &csq->desc[ntc];
210+
head = roce_read(hr_dev, ROCEE_TX_CMQ_HEAD_REG);
211+
while (head != ntc) {
212+
memset(desc, 0, sizeof(*desc));
213+
ntc++;
214+
if (ntc == csq->desc_num)
215+
ntc = 0;
216+
desc = &csq->desc[ntc];
217+
clean++;
218+
}
219+
csq->next_to_clean = ntc;
220+
221+
return clean;
222+
}
223+
224+
int hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
225+
struct hns_roce_cmq_desc *desc, int num)
226+
{
227+
struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
228+
struct hns_roce_v2_cmq_ring *csq = &priv->cmq.csq;
229+
struct hns_roce_cmq_desc *desc_to_use;
230+
bool complete = false;
231+
u32 timeout = 0;
232+
int handle = 0;
233+
u16 desc_ret;
234+
int ret = 0;
235+
int ntc;
236+
237+
spin_lock_bh(&csq->lock);
238+
239+
if (num > hns_roce_cmq_space(csq)) {
240+
spin_unlock_bh(&csq->lock);
241+
return -EBUSY;
242+
}
243+
244+
/*
245+
* Record the location of desc in the cmq for this time
246+
* which will be use for hardware to write back
247+
*/
248+
ntc = csq->next_to_use;
249+
250+
while (handle < num) {
251+
desc_to_use = &csq->desc[csq->next_to_use];
252+
*desc_to_use = desc[handle];
253+
dev_dbg(hr_dev->dev, "set cmq desc:\n");
254+
csq->next_to_use++;
255+
if (csq->next_to_use == csq->desc_num)
256+
csq->next_to_use = 0;
257+
handle++;
258+
}
259+
260+
/* Write to hardware */
261+
roce_write(hr_dev, ROCEE_TX_CMQ_TAIL_REG, csq->next_to_use);
262+
263+
/*
264+
* If the command is sync, wait for the firmware to write back,
265+
* if multi descriptors to be sent, use the first one to check
266+
*/
267+
if ((desc->flag) & HNS_ROCE_CMD_FLAG_NO_INTR) {
268+
do {
269+
if (hns_roce_cmq_csq_done(hr_dev))
270+
break;
271+
usleep_range(1000, 2000);
272+
timeout++;
273+
} while (timeout < priv->cmq.tx_timeout);
274+
}
275+
276+
if (hns_roce_cmq_csq_done(hr_dev)) {
277+
complete = true;
278+
handle = 0;
279+
while (handle < num) {
280+
/* get the result of hardware write back */
281+
desc_to_use = &csq->desc[ntc];
282+
desc[handle] = *desc_to_use;
283+
dev_dbg(hr_dev->dev, "Get cmq desc:\n");
284+
desc_ret = desc[handle].retval;
285+
if (desc_ret == CMD_EXEC_SUCCESS)
286+
ret = 0;
287+
else
288+
ret = -EIO;
289+
priv->cmq.last_status = desc_ret;
290+
ntc++;
291+
handle++;
292+
if (ntc == csq->desc_num)
293+
ntc = 0;
294+
}
295+
}
296+
297+
if (!complete)
298+
ret = -EAGAIN;
299+
300+
/* clean the command send queue */
301+
handle = hns_roce_cmq_csq_clean(hr_dev);
302+
if (handle != num)
303+
dev_warn(hr_dev->dev, "Cleaned %d, need to clean %d\n",
304+
handle, num);
305+
306+
spin_unlock_bh(&csq->lock);
307+
308+
return ret;
309+
}
310+
311+
static const struct hns_roce_hw hns_roce_hw_v2 = {
312+
.cmq_init = hns_roce_v2_cmq_init,
313+
.cmq_exit = hns_roce_v2_cmq_exit,
314+
};
46315

47316
static const struct pci_device_id hns_roce_hw_v2_pci_tbl[] = {
48317
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA), 0},
@@ -87,6 +356,12 @@ static int hns_roce_hw_v2_init_instance(struct hnae3_handle *handle)
87356
if (!hr_dev)
88357
return -ENOMEM;
89358

359+
hr_dev->priv = kzalloc(sizeof(struct hns_roce_v2_priv), GFP_KERNEL);
360+
if (!hr_dev->priv) {
361+
ret = -ENOMEM;
362+
goto error_failed_kzalloc;
363+
}
364+
90365
hr_dev->pci_dev = handle->pdev;
91366
hr_dev->dev = &handle->pdev->dev;
92367
handle->priv = hr_dev;
@@ -106,6 +381,9 @@ static int hns_roce_hw_v2_init_instance(struct hnae3_handle *handle)
106381
return 0;
107382

108383
error_failed_get_cfg:
384+
kfree(hr_dev->priv);
385+
386+
error_failed_kzalloc:
109387
ib_dealloc_device(&hr_dev->ib_dev);
110388

111389
return ret;
@@ -117,6 +395,7 @@ static void hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle,
117395
struct hns_roce_dev *hr_dev = (struct hns_roce_dev *)handle->priv;
118396

119397
hns_roce_exit(hr_dev);
398+
kfree(hr_dev->priv);
120399
ib_dealloc_device(&hr_dev->ib_dev);
121400
}
122401

0 commit comments

Comments
 (0)