aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/compress/octeontx/otx_zip.c
blob: a9046ff351a040b374798b8ebb2a630c4c94f4fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2018 Cavium, Inc
 */

#include "otx_zip.h"

uint64_t
zip_reg_read64(uint8_t *hw_addr, uint64_t offset)
{
	uint8_t *base = hw_addr;
	return *(volatile uint64_t *)(base + offset);
}

void
zip_reg_write64(uint8_t *hw_addr, uint64_t offset, uint64_t val)
{
	uint8_t *base = hw_addr;
	*(uint64_t *)(base + offset) = val;
}

static void
zip_q_enable(struct zipvf_qp *qp)
{
	zip_vqx_ena_t que_ena;

	/*ZIP VFx command queue init*/
	que_ena.u = 0ull;
	que_ena.s.ena = 1;

	zip_reg_write64(qp->vf->vbar0, ZIP_VQ_ENA, que_ena.u);
	rte_wmb();
}

/* initialize given qp on zip device */
int
zipvf_q_init(struct zipvf_qp *qp)
{
	zip_vqx_sbuf_addr_t que_sbuf_addr;

	uint64_t size;
	void *cmdq_addr;
	uint64_t iova;
	struct zipvf_cmdq *cmdq = &qp->cmdq;
	struct zip_vf *vf = qp->vf;

	/* allocate and setup instruction queue */
	size = ZIP_MAX_CMDQ_SIZE;
	size = ZIP_ALIGN_ROUNDUP(size, ZIP_CMDQ_ALIGN);

	cmdq_addr = rte_zmalloc(qp->name, size, ZIP_CMDQ_ALIGN);
	if (cmdq_addr == NULL)
		return -1;

	cmdq->sw_head = (uint64_t *)cmdq_addr;
	cmdq->va = (uint8_t *)cmdq_addr;
	iova = rte_mem_virt2iova(cmdq_addr);

	cmdq->iova = iova;

	que_sbuf_addr.u = 0ull;
	que_sbuf_addr.s.ptr = (cmdq->iova >> 7);
	zip_reg_write64(vf->vbar0, ZIP_VQ_SBUF_ADDR, que_sbuf_addr.u);

	zip_q_enable(qp);

	memset(cmdq->va, 0, ZIP_MAX_CMDQ_SIZE);
	rte_spinlock_init(&cmdq->qlock);

	return 0;
}

int
zipvf_q_term(struct zipvf_qp *qp)
{
	struct zipvf_cmdq *cmdq = &qp->cmdq;
	zip_vqx_ena_t que_ena;
	struct zip_vf *vf = qp->vf;

	if (cmdq->va != NULL) {
		memset(cmdq->va, 0, ZIP_MAX_CMDQ_SIZE);
		rte_free(cmdq->va);
	}

	/*Disabling the ZIP queue*/
	que_ena.u = 0ull;
	zip_reg_write64(vf->vbar0, ZIP_VQ_ENA, que_ena.u);

	return 0;
}

void
zipvf_push_command(struct zipvf_qp *qp, union zip_inst_s *cmd)
{
	zip_quex_doorbell_t dbell;
	union zip_nptr_s ncp;
	uint64_t *ncb_ptr;
	struct zipvf_cmdq *cmdq = &qp->cmdq;
	void *reg_base = qp->vf->vbar0;

	/*Held queue lock*/
	rte_spinlock_lock(&(cmdq->qlock));

	/* Check space availability in zip cmd queue */
	if ((((cmdq->sw_head - (uint64_t *)cmdq->va) * sizeof(uint64_t *)) +
		ZIP_CMD_SIZE) == (ZIP_MAX_CMDQ_SIZE - ZIP_MAX_NCBP_SIZE)) {
		/*Last buffer of the command queue*/
		memcpy((uint8_t *)cmdq->sw_head,
			(uint8_t *)cmd,
			sizeof(union zip_inst_s));
		/* move pointer to next loc in unit of 64-bit word */
		cmdq->sw_head += ZIP_CMD_SIZE_WORDS;

		/* now, point the "Next-Chunk Buffer Ptr" to sw_head */
		ncb_ptr = cmdq->sw_head;
		/* Pointing head again to cmdqueue base*/
		cmdq->sw_head = (uint64_t *)cmdq->va;

		ncp.u = 0ull;
		ncp.s.addr = cmdq->iova;
		*ncb_ptr = ncp.u;
	} else {
		/*Enough buffers available in the command queue*/
		memcpy((uint8_t *)cmdq->sw_head,
			(uint8_t *)cmd,
			sizeof(union zip_inst_s));
		cmdq->sw_head += ZIP_CMD_SIZE_WORDS;
	}

	rte_wmb();

	/* Ringing ZIP VF doorbell */
	dbell.u = 0ull;
	dbell.s.dbell_cnt = 1;
	zip_reg_write64(reg_base, ZIP_VQ_DOORBELL, dbell.u);

	rte_spinlock_unlock(&(cmdq->qlock));
}

int
zipvf_create(struct rte_compressdev *compressdev)
{
	struct   rte_pci_device *pdev = RTE_DEV_TO_PCI(compressdev->device);
	struct   zip_vf *zipvf = NULL;
	char     *dev_name = compressdev->data->name;
	void     *vbar0;
	uint64_t reg;

	if (pdev->mem_resource[0].phys_addr == 0ULL)
		return -EIO;

	vbar0 = pdev->mem_resource[0].addr;
	if (!vbar0) {
		ZIP_PMD_ERR("Failed to map BAR0 of %s", dev_name);
		return -ENODEV;
	}

	zipvf = (struct zip_vf *)(compressdev->data->dev_private);

	if (!zipvf)
		return -ENOMEM;

	zipvf->vbar0 = vbar0;
	reg = zip_reg_read64(zipvf->vbar0, ZIP_VF_PF_MBOXX(0));
	/* Storing domain in local to ZIP VF */
	zipvf->dom_sdom = reg;
	zipvf->pdev = pdev;
	zipvf->max_nb_queue_pairs = ZIP_MAX_VF_QUEUE;
	return 0;
}

int
zipvf_destroy(struct rte_compressdev *compressdev)
{
	struct zip_vf *vf = (struct zip_vf *)(compressdev->data->dev_private);

	/* Rewriting the domain_id in ZIP_VF_MBOX for app rerun */
	zip_reg_write64(vf->vbar0, ZIP_VF_PF_MBOXX(0), vf->dom_sdom);

	return 0;
}