xref: /OK3568_Linux_fs/kernel/drivers/crypto/ccree/cc_request_mgr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/kernel.h>
5*4882a593Smuzhiyun #include <linux/nospec.h>
6*4882a593Smuzhiyun #include "cc_driver.h"
7*4882a593Smuzhiyun #include "cc_buffer_mgr.h"
8*4882a593Smuzhiyun #include "cc_request_mgr.h"
9*4882a593Smuzhiyun #include "cc_pm.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define CC_MAX_POLL_ITER	10
12*4882a593Smuzhiyun /* The highest descriptor count in used */
13*4882a593Smuzhiyun #define CC_MAX_DESC_SEQ_LEN	23
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct cc_req_mgr_handle {
16*4882a593Smuzhiyun 	/* Request manager resources */
17*4882a593Smuzhiyun 	unsigned int hw_queue_size; /* HW capability */
18*4882a593Smuzhiyun 	unsigned int min_free_hw_slots;
19*4882a593Smuzhiyun 	unsigned int max_used_sw_slots;
20*4882a593Smuzhiyun 	struct cc_crypto_req req_queue[MAX_REQUEST_QUEUE_SIZE];
21*4882a593Smuzhiyun 	u32 req_queue_head;
22*4882a593Smuzhiyun 	u32 req_queue_tail;
23*4882a593Smuzhiyun 	u32 axi_completed;
24*4882a593Smuzhiyun 	u32 q_free_slots;
25*4882a593Smuzhiyun 	/* This lock protects access to HW register
26*4882a593Smuzhiyun 	 * that must be single request at a time
27*4882a593Smuzhiyun 	 */
28*4882a593Smuzhiyun 	spinlock_t hw_lock;
29*4882a593Smuzhiyun 	struct cc_hw_desc compl_desc;
30*4882a593Smuzhiyun 	u8 *dummy_comp_buff;
31*4882a593Smuzhiyun 	dma_addr_t dummy_comp_buff_dma;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	/* backlog queue */
34*4882a593Smuzhiyun 	struct list_head backlog;
35*4882a593Smuzhiyun 	unsigned int bl_len;
36*4882a593Smuzhiyun 	spinlock_t bl_lock; /* protect backlog queue */
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #ifdef COMP_IN_WQ
39*4882a593Smuzhiyun 	struct workqueue_struct *workq;
40*4882a593Smuzhiyun 	struct delayed_work compwork;
41*4882a593Smuzhiyun #else
42*4882a593Smuzhiyun 	struct tasklet_struct comptask;
43*4882a593Smuzhiyun #endif
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun struct cc_bl_item {
47*4882a593Smuzhiyun 	struct cc_crypto_req creq;
48*4882a593Smuzhiyun 	struct cc_hw_desc desc[CC_MAX_DESC_SEQ_LEN];
49*4882a593Smuzhiyun 	unsigned int len;
50*4882a593Smuzhiyun 	struct list_head list;
51*4882a593Smuzhiyun 	bool notif;
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun static const u32 cc_cpp_int_masks[CC_CPP_NUM_ALGS][CC_CPP_NUM_SLOTS] = {
55*4882a593Smuzhiyun 	{ BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_0_INT_BIT_SHIFT),
56*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_1_INT_BIT_SHIFT),
57*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_2_INT_BIT_SHIFT),
58*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_3_INT_BIT_SHIFT),
59*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_4_INT_BIT_SHIFT),
60*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_5_INT_BIT_SHIFT),
61*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_6_INT_BIT_SHIFT),
62*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_AES_7_INT_BIT_SHIFT) },
63*4882a593Smuzhiyun 	{ BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_0_INT_BIT_SHIFT),
64*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_1_INT_BIT_SHIFT),
65*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_2_INT_BIT_SHIFT),
66*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_3_INT_BIT_SHIFT),
67*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_4_INT_BIT_SHIFT),
68*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_5_INT_BIT_SHIFT),
69*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_6_INT_BIT_SHIFT),
70*4882a593Smuzhiyun 	  BIT(CC_HOST_IRR_REE_OP_ABORTED_SM_7_INT_BIT_SHIFT) }
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun static void comp_handler(unsigned long devarg);
74*4882a593Smuzhiyun #ifdef COMP_IN_WQ
75*4882a593Smuzhiyun static void comp_work_handler(struct work_struct *work);
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun 
cc_cpp_int_mask(enum cc_cpp_alg alg,int slot)78*4882a593Smuzhiyun static inline u32 cc_cpp_int_mask(enum cc_cpp_alg alg, int slot)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	alg = array_index_nospec(alg, CC_CPP_NUM_ALGS);
81*4882a593Smuzhiyun 	slot = array_index_nospec(slot, CC_CPP_NUM_SLOTS);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	return cc_cpp_int_masks[alg][slot];
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
cc_req_mgr_fini(struct cc_drvdata * drvdata)86*4882a593Smuzhiyun void cc_req_mgr_fini(struct cc_drvdata *drvdata)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
89*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (!req_mgr_h)
92*4882a593Smuzhiyun 		return; /* Not allocated */
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (req_mgr_h->dummy_comp_buff_dma) {
95*4882a593Smuzhiyun 		dma_free_coherent(dev, sizeof(u32), req_mgr_h->dummy_comp_buff,
96*4882a593Smuzhiyun 				  req_mgr_h->dummy_comp_buff_dma);
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	dev_dbg(dev, "max_used_hw_slots=%d\n", (req_mgr_h->hw_queue_size -
100*4882a593Smuzhiyun 						req_mgr_h->min_free_hw_slots));
101*4882a593Smuzhiyun 	dev_dbg(dev, "max_used_sw_slots=%d\n", req_mgr_h->max_used_sw_slots);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #ifdef COMP_IN_WQ
104*4882a593Smuzhiyun 	flush_workqueue(req_mgr_h->workq);
105*4882a593Smuzhiyun 	destroy_workqueue(req_mgr_h->workq);
106*4882a593Smuzhiyun #else
107*4882a593Smuzhiyun 	/* Kill tasklet */
108*4882a593Smuzhiyun 	tasklet_kill(&req_mgr_h->comptask);
109*4882a593Smuzhiyun #endif
110*4882a593Smuzhiyun 	kfree_sensitive(req_mgr_h);
111*4882a593Smuzhiyun 	drvdata->request_mgr_handle = NULL;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
cc_req_mgr_init(struct cc_drvdata * drvdata)114*4882a593Smuzhiyun int cc_req_mgr_init(struct cc_drvdata *drvdata)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct cc_req_mgr_handle *req_mgr_h;
117*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
118*4882a593Smuzhiyun 	int rc = 0;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	req_mgr_h = kzalloc(sizeof(*req_mgr_h), GFP_KERNEL);
121*4882a593Smuzhiyun 	if (!req_mgr_h) {
122*4882a593Smuzhiyun 		rc = -ENOMEM;
123*4882a593Smuzhiyun 		goto req_mgr_init_err;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	drvdata->request_mgr_handle = req_mgr_h;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	spin_lock_init(&req_mgr_h->hw_lock);
129*4882a593Smuzhiyun 	spin_lock_init(&req_mgr_h->bl_lock);
130*4882a593Smuzhiyun 	INIT_LIST_HEAD(&req_mgr_h->backlog);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun #ifdef COMP_IN_WQ
133*4882a593Smuzhiyun 	dev_dbg(dev, "Initializing completion workqueue\n");
134*4882a593Smuzhiyun 	req_mgr_h->workq = create_singlethread_workqueue("ccree");
135*4882a593Smuzhiyun 	if (!req_mgr_h->workq) {
136*4882a593Smuzhiyun 		dev_err(dev, "Failed creating work queue\n");
137*4882a593Smuzhiyun 		rc = -ENOMEM;
138*4882a593Smuzhiyun 		goto req_mgr_init_err;
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&req_mgr_h->compwork, comp_work_handler);
141*4882a593Smuzhiyun #else
142*4882a593Smuzhiyun 	dev_dbg(dev, "Initializing completion tasklet\n");
143*4882a593Smuzhiyun 	tasklet_init(&req_mgr_h->comptask, comp_handler,
144*4882a593Smuzhiyun 		     (unsigned long)drvdata);
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun 	req_mgr_h->hw_queue_size = cc_ioread(drvdata,
147*4882a593Smuzhiyun 					     CC_REG(DSCRPTR_QUEUE_SRAM_SIZE));
148*4882a593Smuzhiyun 	dev_dbg(dev, "hw_queue_size=0x%08X\n", req_mgr_h->hw_queue_size);
149*4882a593Smuzhiyun 	if (req_mgr_h->hw_queue_size < MIN_HW_QUEUE_SIZE) {
150*4882a593Smuzhiyun 		dev_err(dev, "Invalid HW queue size = %u (Min. required is %u)\n",
151*4882a593Smuzhiyun 			req_mgr_h->hw_queue_size, MIN_HW_QUEUE_SIZE);
152*4882a593Smuzhiyun 		rc = -ENOMEM;
153*4882a593Smuzhiyun 		goto req_mgr_init_err;
154*4882a593Smuzhiyun 	}
155*4882a593Smuzhiyun 	req_mgr_h->min_free_hw_slots = req_mgr_h->hw_queue_size;
156*4882a593Smuzhiyun 	req_mgr_h->max_used_sw_slots = 0;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	/* Allocate DMA word for "dummy" completion descriptor use */
159*4882a593Smuzhiyun 	req_mgr_h->dummy_comp_buff =
160*4882a593Smuzhiyun 		dma_alloc_coherent(dev, sizeof(u32),
161*4882a593Smuzhiyun 				   &req_mgr_h->dummy_comp_buff_dma,
162*4882a593Smuzhiyun 				   GFP_KERNEL);
163*4882a593Smuzhiyun 	if (!req_mgr_h->dummy_comp_buff) {
164*4882a593Smuzhiyun 		dev_err(dev, "Not enough memory to allocate DMA (%zu) dropped buffer\n",
165*4882a593Smuzhiyun 			sizeof(u32));
166*4882a593Smuzhiyun 		rc = -ENOMEM;
167*4882a593Smuzhiyun 		goto req_mgr_init_err;
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* Init. "dummy" completion descriptor */
171*4882a593Smuzhiyun 	hw_desc_init(&req_mgr_h->compl_desc);
172*4882a593Smuzhiyun 	set_din_const(&req_mgr_h->compl_desc, 0, sizeof(u32));
173*4882a593Smuzhiyun 	set_dout_dlli(&req_mgr_h->compl_desc, req_mgr_h->dummy_comp_buff_dma,
174*4882a593Smuzhiyun 		      sizeof(u32), NS_BIT, 1);
175*4882a593Smuzhiyun 	set_flow_mode(&req_mgr_h->compl_desc, BYPASS);
176*4882a593Smuzhiyun 	set_queue_last_ind(drvdata, &req_mgr_h->compl_desc);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	return 0;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun req_mgr_init_err:
181*4882a593Smuzhiyun 	cc_req_mgr_fini(drvdata);
182*4882a593Smuzhiyun 	return rc;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
enqueue_seq(struct cc_drvdata * drvdata,struct cc_hw_desc seq[],unsigned int seq_len)185*4882a593Smuzhiyun static void enqueue_seq(struct cc_drvdata *drvdata, struct cc_hw_desc seq[],
186*4882a593Smuzhiyun 			unsigned int seq_len)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	int i, w;
189*4882a593Smuzhiyun 	void __iomem *reg = drvdata->cc_base + CC_REG(DSCRPTR_QUEUE_WORD0);
190*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/*
193*4882a593Smuzhiyun 	 * We do indeed write all 6 command words to the same
194*4882a593Smuzhiyun 	 * register. The HW supports this.
195*4882a593Smuzhiyun 	 */
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	for (i = 0; i < seq_len; i++) {
198*4882a593Smuzhiyun 		for (w = 0; w <= 5; w++)
199*4882a593Smuzhiyun 			writel_relaxed(seq[i].word[w], reg);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 		if (cc_dump_desc)
202*4882a593Smuzhiyun 			dev_dbg(dev, "desc[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\n",
203*4882a593Smuzhiyun 				i, seq[i].word[0], seq[i].word[1],
204*4882a593Smuzhiyun 				seq[i].word[2], seq[i].word[3],
205*4882a593Smuzhiyun 				seq[i].word[4], seq[i].word[5]);
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun /**
210*4882a593Smuzhiyun  * request_mgr_complete() - Completion will take place if and only if user
211*4882a593Smuzhiyun  * requested completion by cc_send_sync_request().
212*4882a593Smuzhiyun  *
213*4882a593Smuzhiyun  * @dev: Device pointer
214*4882a593Smuzhiyun  * @dx_compl_h: The completion event to signal
215*4882a593Smuzhiyun  * @dummy: unused error code
216*4882a593Smuzhiyun  */
request_mgr_complete(struct device * dev,void * dx_compl_h,int dummy)217*4882a593Smuzhiyun static void request_mgr_complete(struct device *dev, void *dx_compl_h,
218*4882a593Smuzhiyun 				 int dummy)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	struct completion *this_compl = dx_compl_h;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	complete(this_compl);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
cc_queues_status(struct cc_drvdata * drvdata,struct cc_req_mgr_handle * req_mgr_h,unsigned int total_seq_len)225*4882a593Smuzhiyun static int cc_queues_status(struct cc_drvdata *drvdata,
226*4882a593Smuzhiyun 			    struct cc_req_mgr_handle *req_mgr_h,
227*4882a593Smuzhiyun 			    unsigned int total_seq_len)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun 	unsigned long poll_queue;
230*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	/* SW queue is checked only once as it will not
233*4882a593Smuzhiyun 	 * be changed during the poll because the spinlock_bh
234*4882a593Smuzhiyun 	 * is held by the thread
235*4882a593Smuzhiyun 	 */
236*4882a593Smuzhiyun 	if (((req_mgr_h->req_queue_head + 1) & (MAX_REQUEST_QUEUE_SIZE - 1)) ==
237*4882a593Smuzhiyun 	    req_mgr_h->req_queue_tail) {
238*4882a593Smuzhiyun 		dev_err(dev, "SW FIFO is full. req_queue_head=%d sw_fifo_len=%d\n",
239*4882a593Smuzhiyun 			req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE);
240*4882a593Smuzhiyun 		return -ENOSPC;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (req_mgr_h->q_free_slots >= total_seq_len)
244*4882a593Smuzhiyun 		return 0;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	/* Wait for space in HW queue. Poll constant num of iterations. */
247*4882a593Smuzhiyun 	for (poll_queue = 0; poll_queue < CC_MAX_POLL_ITER ; poll_queue++) {
248*4882a593Smuzhiyun 		req_mgr_h->q_free_slots =
249*4882a593Smuzhiyun 			cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
250*4882a593Smuzhiyun 		if (req_mgr_h->q_free_slots < req_mgr_h->min_free_hw_slots)
251*4882a593Smuzhiyun 			req_mgr_h->min_free_hw_slots = req_mgr_h->q_free_slots;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 		if (req_mgr_h->q_free_slots >= total_seq_len) {
254*4882a593Smuzhiyun 			/* If there is enough place return */
255*4882a593Smuzhiyun 			return 0;
256*4882a593Smuzhiyun 		}
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 		dev_dbg(dev, "HW FIFO is full. q_free_slots=%d total_seq_len=%d\n",
259*4882a593Smuzhiyun 			req_mgr_h->q_free_slots, total_seq_len);
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 	/* No room in the HW queue try again later */
262*4882a593Smuzhiyun 	dev_dbg(dev, "HW FIFO full, timeout. req_queue_head=%d sw_fifo_len=%d q_free_slots=%d total_seq_len=%d\n",
263*4882a593Smuzhiyun 		req_mgr_h->req_queue_head, MAX_REQUEST_QUEUE_SIZE,
264*4882a593Smuzhiyun 		req_mgr_h->q_free_slots, total_seq_len);
265*4882a593Smuzhiyun 	return -ENOSPC;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /**
269*4882a593Smuzhiyun  * cc_do_send_request() - Enqueue caller request to crypto hardware.
270*4882a593Smuzhiyun  * Need to be called with HW lock held and PM running
271*4882a593Smuzhiyun  *
272*4882a593Smuzhiyun  * @drvdata: Associated device driver context
273*4882a593Smuzhiyun  * @cc_req: The request to enqueue
274*4882a593Smuzhiyun  * @desc: The crypto sequence
275*4882a593Smuzhiyun  * @len: The crypto sequence length
276*4882a593Smuzhiyun  * @add_comp: If "true": add an artificial dout DMA to mark completion
277*4882a593Smuzhiyun  *
278*4882a593Smuzhiyun  */
cc_do_send_request(struct cc_drvdata * drvdata,struct cc_crypto_req * cc_req,struct cc_hw_desc * desc,unsigned int len,bool add_comp)279*4882a593Smuzhiyun static void cc_do_send_request(struct cc_drvdata *drvdata,
280*4882a593Smuzhiyun 			       struct cc_crypto_req *cc_req,
281*4882a593Smuzhiyun 			       struct cc_hw_desc *desc, unsigned int len,
282*4882a593Smuzhiyun 			       bool add_comp)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun 	struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
285*4882a593Smuzhiyun 	unsigned int used_sw_slots;
286*4882a593Smuzhiyun 	unsigned int total_seq_len = len; /*initial sequence length*/
287*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	used_sw_slots = ((req_mgr_h->req_queue_head -
290*4882a593Smuzhiyun 			  req_mgr_h->req_queue_tail) &
291*4882a593Smuzhiyun 			 (MAX_REQUEST_QUEUE_SIZE - 1));
292*4882a593Smuzhiyun 	if (used_sw_slots > req_mgr_h->max_used_sw_slots)
293*4882a593Smuzhiyun 		req_mgr_h->max_used_sw_slots = used_sw_slots;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	/* Enqueue request - must be locked with HW lock*/
296*4882a593Smuzhiyun 	req_mgr_h->req_queue[req_mgr_h->req_queue_head] = *cc_req;
297*4882a593Smuzhiyun 	req_mgr_h->req_queue_head = (req_mgr_h->req_queue_head + 1) &
298*4882a593Smuzhiyun 				    (MAX_REQUEST_QUEUE_SIZE - 1);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	dev_dbg(dev, "Enqueue request head=%u\n", req_mgr_h->req_queue_head);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	/*
303*4882a593Smuzhiyun 	 * We are about to push command to the HW via the command registers
304*4882a593Smuzhiyun 	 * that may reference host memory. We need to issue a memory barrier
305*4882a593Smuzhiyun 	 * to make sure there are no outstanding memory writes
306*4882a593Smuzhiyun 	 */
307*4882a593Smuzhiyun 	wmb();
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	/* STAT_PHASE_4: Push sequence */
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	enqueue_seq(drvdata, desc, len);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	if (add_comp) {
314*4882a593Smuzhiyun 		enqueue_seq(drvdata, &req_mgr_h->compl_desc, 1);
315*4882a593Smuzhiyun 		total_seq_len++;
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	if (req_mgr_h->q_free_slots < total_seq_len) {
319*4882a593Smuzhiyun 		/* This situation should never occur. Maybe indicating problem
320*4882a593Smuzhiyun 		 * with resuming power. Set the free slot count to 0 and hope
321*4882a593Smuzhiyun 		 * for the best.
322*4882a593Smuzhiyun 		 */
323*4882a593Smuzhiyun 		dev_err(dev, "HW free slot count mismatch.");
324*4882a593Smuzhiyun 		req_mgr_h->q_free_slots = 0;
325*4882a593Smuzhiyun 	} else {
326*4882a593Smuzhiyun 		/* Update the free slots in HW queue */
327*4882a593Smuzhiyun 		req_mgr_h->q_free_slots -= total_seq_len;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
cc_enqueue_backlog(struct cc_drvdata * drvdata,struct cc_bl_item * bli)331*4882a593Smuzhiyun static void cc_enqueue_backlog(struct cc_drvdata *drvdata,
332*4882a593Smuzhiyun 			       struct cc_bl_item *bli)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
335*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	spin_lock_bh(&mgr->bl_lock);
338*4882a593Smuzhiyun 	list_add_tail(&bli->list, &mgr->backlog);
339*4882a593Smuzhiyun 	++mgr->bl_len;
340*4882a593Smuzhiyun 	dev_dbg(dev, "+++bl len: %d\n", mgr->bl_len);
341*4882a593Smuzhiyun 	spin_unlock_bh(&mgr->bl_lock);
342*4882a593Smuzhiyun 	tasklet_schedule(&mgr->comptask);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun 
cc_proc_backlog(struct cc_drvdata * drvdata)345*4882a593Smuzhiyun static void cc_proc_backlog(struct cc_drvdata *drvdata)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
348*4882a593Smuzhiyun 	struct cc_bl_item *bli;
349*4882a593Smuzhiyun 	struct cc_crypto_req *creq;
350*4882a593Smuzhiyun 	void *req;
351*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
352*4882a593Smuzhiyun 	int rc;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	spin_lock(&mgr->bl_lock);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	while (mgr->bl_len) {
357*4882a593Smuzhiyun 		bli = list_first_entry(&mgr->backlog, struct cc_bl_item, list);
358*4882a593Smuzhiyun 		dev_dbg(dev, "---bl len: %d\n", mgr->bl_len);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 		spin_unlock(&mgr->bl_lock);
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 		creq = &bli->creq;
364*4882a593Smuzhiyun 		req = creq->user_arg;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 		/*
367*4882a593Smuzhiyun 		 * Notify the request we're moving out of the backlog
368*4882a593Smuzhiyun 		 * but only if we haven't done so already.
369*4882a593Smuzhiyun 		 */
370*4882a593Smuzhiyun 		if (!bli->notif) {
371*4882a593Smuzhiyun 			creq->user_cb(dev, req, -EINPROGRESS);
372*4882a593Smuzhiyun 			bli->notif = true;
373*4882a593Smuzhiyun 		}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 		spin_lock(&mgr->hw_lock);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 		rc = cc_queues_status(drvdata, mgr, bli->len);
378*4882a593Smuzhiyun 		if (rc) {
379*4882a593Smuzhiyun 			/*
380*4882a593Smuzhiyun 			 * There is still no room in the FIFO for
381*4882a593Smuzhiyun 			 * this request. Bail out. We'll return here
382*4882a593Smuzhiyun 			 * on the next completion irq.
383*4882a593Smuzhiyun 			 */
384*4882a593Smuzhiyun 			spin_unlock(&mgr->hw_lock);
385*4882a593Smuzhiyun 			return;
386*4882a593Smuzhiyun 		}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		cc_do_send_request(drvdata, &bli->creq, bli->desc, bli->len,
389*4882a593Smuzhiyun 				   false);
390*4882a593Smuzhiyun 		spin_unlock(&mgr->hw_lock);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 		/* Remove ourselves from the backlog list */
393*4882a593Smuzhiyun 		spin_lock(&mgr->bl_lock);
394*4882a593Smuzhiyun 		list_del(&bli->list);
395*4882a593Smuzhiyun 		--mgr->bl_len;
396*4882a593Smuzhiyun 		kfree(bli);
397*4882a593Smuzhiyun 	}
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	spin_unlock(&mgr->bl_lock);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun 
cc_send_request(struct cc_drvdata * drvdata,struct cc_crypto_req * cc_req,struct cc_hw_desc * desc,unsigned int len,struct crypto_async_request * req)402*4882a593Smuzhiyun int cc_send_request(struct cc_drvdata *drvdata, struct cc_crypto_req *cc_req,
403*4882a593Smuzhiyun 		    struct cc_hw_desc *desc, unsigned int len,
404*4882a593Smuzhiyun 		    struct crypto_async_request *req)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun 	int rc;
407*4882a593Smuzhiyun 	struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
408*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
409*4882a593Smuzhiyun 	bool backlog_ok = req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG;
410*4882a593Smuzhiyun 	gfp_t flags = cc_gfp_flags(req);
411*4882a593Smuzhiyun 	struct cc_bl_item *bli;
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	rc = cc_pm_get(dev);
414*4882a593Smuzhiyun 	if (rc) {
415*4882a593Smuzhiyun 		dev_err(dev, "cc_pm_get returned %x\n", rc);
416*4882a593Smuzhiyun 		return rc;
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	spin_lock_bh(&mgr->hw_lock);
420*4882a593Smuzhiyun 	rc = cc_queues_status(drvdata, mgr, len);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun #ifdef CC_DEBUG_FORCE_BACKLOG
423*4882a593Smuzhiyun 	if (backlog_ok)
424*4882a593Smuzhiyun 		rc = -ENOSPC;
425*4882a593Smuzhiyun #endif /* CC_DEBUG_FORCE_BACKLOG */
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	if (rc == -ENOSPC && backlog_ok) {
428*4882a593Smuzhiyun 		spin_unlock_bh(&mgr->hw_lock);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 		bli = kmalloc(sizeof(*bli), flags);
431*4882a593Smuzhiyun 		if (!bli) {
432*4882a593Smuzhiyun 			cc_pm_put_suspend(dev);
433*4882a593Smuzhiyun 			return -ENOMEM;
434*4882a593Smuzhiyun 		}
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 		memcpy(&bli->creq, cc_req, sizeof(*cc_req));
437*4882a593Smuzhiyun 		memcpy(&bli->desc, desc, len * sizeof(*desc));
438*4882a593Smuzhiyun 		bli->len = len;
439*4882a593Smuzhiyun 		bli->notif = false;
440*4882a593Smuzhiyun 		cc_enqueue_backlog(drvdata, bli);
441*4882a593Smuzhiyun 		return -EBUSY;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	if (!rc) {
445*4882a593Smuzhiyun 		cc_do_send_request(drvdata, cc_req, desc, len, false);
446*4882a593Smuzhiyun 		rc = -EINPROGRESS;
447*4882a593Smuzhiyun 	}
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	spin_unlock_bh(&mgr->hw_lock);
450*4882a593Smuzhiyun 	return rc;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
cc_send_sync_request(struct cc_drvdata * drvdata,struct cc_crypto_req * cc_req,struct cc_hw_desc * desc,unsigned int len)453*4882a593Smuzhiyun int cc_send_sync_request(struct cc_drvdata *drvdata,
454*4882a593Smuzhiyun 			 struct cc_crypto_req *cc_req, struct cc_hw_desc *desc,
455*4882a593Smuzhiyun 			 unsigned int len)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	int rc;
458*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
459*4882a593Smuzhiyun 	struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	init_completion(&cc_req->seq_compl);
462*4882a593Smuzhiyun 	cc_req->user_cb = request_mgr_complete;
463*4882a593Smuzhiyun 	cc_req->user_arg = &cc_req->seq_compl;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	rc = cc_pm_get(dev);
466*4882a593Smuzhiyun 	if (rc) {
467*4882a593Smuzhiyun 		dev_err(dev, "cc_pm_get returned %x\n", rc);
468*4882a593Smuzhiyun 		return rc;
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	while (true) {
472*4882a593Smuzhiyun 		spin_lock_bh(&mgr->hw_lock);
473*4882a593Smuzhiyun 		rc = cc_queues_status(drvdata, mgr, len + 1);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 		if (!rc)
476*4882a593Smuzhiyun 			break;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 		spin_unlock_bh(&mgr->hw_lock);
479*4882a593Smuzhiyun 		wait_for_completion_interruptible(&drvdata->hw_queue_avail);
480*4882a593Smuzhiyun 		reinit_completion(&drvdata->hw_queue_avail);
481*4882a593Smuzhiyun 	}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	cc_do_send_request(drvdata, cc_req, desc, len, true);
484*4882a593Smuzhiyun 	spin_unlock_bh(&mgr->hw_lock);
485*4882a593Smuzhiyun 	wait_for_completion(&cc_req->seq_compl);
486*4882a593Smuzhiyun 	return 0;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun /**
490*4882a593Smuzhiyun  * send_request_init() - Enqueue caller request to crypto hardware during init
491*4882a593Smuzhiyun  * process.
492*4882a593Smuzhiyun  * Assume this function is not called in the middle of a flow,
493*4882a593Smuzhiyun  * since we set QUEUE_LAST_IND flag in the last descriptor.
494*4882a593Smuzhiyun  *
495*4882a593Smuzhiyun  * @drvdata: Associated device driver context
496*4882a593Smuzhiyun  * @desc: The crypto sequence
497*4882a593Smuzhiyun  * @len: The crypto sequence length
498*4882a593Smuzhiyun  *
499*4882a593Smuzhiyun  * Return:
500*4882a593Smuzhiyun  * Returns "0" upon success
501*4882a593Smuzhiyun  */
send_request_init(struct cc_drvdata * drvdata,struct cc_hw_desc * desc,unsigned int len)502*4882a593Smuzhiyun int send_request_init(struct cc_drvdata *drvdata, struct cc_hw_desc *desc,
503*4882a593Smuzhiyun 		      unsigned int len)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun 	struct cc_req_mgr_handle *req_mgr_h = drvdata->request_mgr_handle;
506*4882a593Smuzhiyun 	unsigned int total_seq_len = len; /*initial sequence length*/
507*4882a593Smuzhiyun 	int rc = 0;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	/* Wait for space in HW and SW FIFO. Poll for as much as FIFO_TIMEOUT.
510*4882a593Smuzhiyun 	 */
511*4882a593Smuzhiyun 	rc = cc_queues_status(drvdata, req_mgr_h, total_seq_len);
512*4882a593Smuzhiyun 	if (rc)
513*4882a593Smuzhiyun 		return rc;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	set_queue_last_ind(drvdata, &desc[(len - 1)]);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	/*
518*4882a593Smuzhiyun 	 * We are about to push command to the HW via the command registers
519*4882a593Smuzhiyun 	 * that may reference host memory. We need to issue a memory barrier
520*4882a593Smuzhiyun 	 * to make sure there are no outstanding memory writes
521*4882a593Smuzhiyun 	 */
522*4882a593Smuzhiyun 	wmb();
523*4882a593Smuzhiyun 	enqueue_seq(drvdata, desc, len);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	/* Update the free slots in HW queue */
526*4882a593Smuzhiyun 	req_mgr_h->q_free_slots =
527*4882a593Smuzhiyun 		cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	return 0;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
complete_request(struct cc_drvdata * drvdata)532*4882a593Smuzhiyun void complete_request(struct cc_drvdata *drvdata)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	struct cc_req_mgr_handle *request_mgr_handle =
535*4882a593Smuzhiyun 						drvdata->request_mgr_handle;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	complete(&drvdata->hw_queue_avail);
538*4882a593Smuzhiyun #ifdef COMP_IN_WQ
539*4882a593Smuzhiyun 	queue_delayed_work(request_mgr_handle->workq,
540*4882a593Smuzhiyun 			   &request_mgr_handle->compwork, 0);
541*4882a593Smuzhiyun #else
542*4882a593Smuzhiyun 	tasklet_schedule(&request_mgr_handle->comptask);
543*4882a593Smuzhiyun #endif
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun #ifdef COMP_IN_WQ
comp_work_handler(struct work_struct * work)547*4882a593Smuzhiyun static void comp_work_handler(struct work_struct *work)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct cc_drvdata *drvdata =
550*4882a593Smuzhiyun 		container_of(work, struct cc_drvdata, compwork.work);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	comp_handler((unsigned long)drvdata);
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun #endif
555*4882a593Smuzhiyun 
proc_completions(struct cc_drvdata * drvdata)556*4882a593Smuzhiyun static void proc_completions(struct cc_drvdata *drvdata)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 	struct cc_crypto_req *cc_req;
559*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
560*4882a593Smuzhiyun 	struct cc_req_mgr_handle *request_mgr_handle =
561*4882a593Smuzhiyun 						drvdata->request_mgr_handle;
562*4882a593Smuzhiyun 	unsigned int *tail = &request_mgr_handle->req_queue_tail;
563*4882a593Smuzhiyun 	unsigned int *head = &request_mgr_handle->req_queue_head;
564*4882a593Smuzhiyun 	int rc;
565*4882a593Smuzhiyun 	u32 mask;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	while (request_mgr_handle->axi_completed) {
568*4882a593Smuzhiyun 		request_mgr_handle->axi_completed--;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 		/* Dequeue request */
571*4882a593Smuzhiyun 		if (*head == *tail) {
572*4882a593Smuzhiyun 			/* We are supposed to handle a completion but our
573*4882a593Smuzhiyun 			 * queue is empty. This is not normal. Return and
574*4882a593Smuzhiyun 			 * hope for the best.
575*4882a593Smuzhiyun 			 */
576*4882a593Smuzhiyun 			dev_err(dev, "Request queue is empty head == tail %u\n",
577*4882a593Smuzhiyun 				*head);
578*4882a593Smuzhiyun 			break;
579*4882a593Smuzhiyun 		}
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 		cc_req = &request_mgr_handle->req_queue[*tail];
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 		if (cc_req->cpp.is_cpp) {
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 			dev_dbg(dev, "CPP request completion slot: %d alg:%d\n",
586*4882a593Smuzhiyun 				cc_req->cpp.slot, cc_req->cpp.alg);
587*4882a593Smuzhiyun 			mask = cc_cpp_int_mask(cc_req->cpp.alg,
588*4882a593Smuzhiyun 					       cc_req->cpp.slot);
589*4882a593Smuzhiyun 			rc = (drvdata->irq & mask ? -EPERM : 0);
590*4882a593Smuzhiyun 			dev_dbg(dev, "Got mask: %x irq: %x rc: %d\n", mask,
591*4882a593Smuzhiyun 				drvdata->irq, rc);
592*4882a593Smuzhiyun 		} else {
593*4882a593Smuzhiyun 			dev_dbg(dev, "None CPP request completion\n");
594*4882a593Smuzhiyun 			rc = 0;
595*4882a593Smuzhiyun 		}
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 		if (cc_req->user_cb)
598*4882a593Smuzhiyun 			cc_req->user_cb(dev, cc_req->user_arg, rc);
599*4882a593Smuzhiyun 		*tail = (*tail + 1) & (MAX_REQUEST_QUEUE_SIZE - 1);
600*4882a593Smuzhiyun 		dev_dbg(dev, "Dequeue request tail=%u\n", *tail);
601*4882a593Smuzhiyun 		dev_dbg(dev, "Request completed. axi_completed=%d\n",
602*4882a593Smuzhiyun 			request_mgr_handle->axi_completed);
603*4882a593Smuzhiyun 		cc_pm_put_suspend(dev);
604*4882a593Smuzhiyun 	}
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun 
cc_axi_comp_count(struct cc_drvdata * drvdata)607*4882a593Smuzhiyun static inline u32 cc_axi_comp_count(struct cc_drvdata *drvdata)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	return FIELD_GET(AXIM_MON_COMP_VALUE,
610*4882a593Smuzhiyun 			 cc_ioread(drvdata, drvdata->axim_mon_offset));
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun /* Deferred service handler, run as interrupt-fired tasklet */
comp_handler(unsigned long devarg)614*4882a593Smuzhiyun static void comp_handler(unsigned long devarg)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	struct cc_drvdata *drvdata = (struct cc_drvdata *)devarg;
617*4882a593Smuzhiyun 	struct cc_req_mgr_handle *request_mgr_handle =
618*4882a593Smuzhiyun 						drvdata->request_mgr_handle;
619*4882a593Smuzhiyun 	struct device *dev = drvdata_to_dev(drvdata);
620*4882a593Smuzhiyun 	u32 irq;
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	dev_dbg(dev, "Completion handler called!\n");
623*4882a593Smuzhiyun 	irq = (drvdata->irq & drvdata->comp_mask);
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	/* To avoid the interrupt from firing as we unmask it,
626*4882a593Smuzhiyun 	 * we clear it now
627*4882a593Smuzhiyun 	 */
628*4882a593Smuzhiyun 	cc_iowrite(drvdata, CC_REG(HOST_ICR), irq);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	/* Avoid race with above clear: Test completion counter once more */
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	request_mgr_handle->axi_completed += cc_axi_comp_count(drvdata);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	dev_dbg(dev, "AXI completion after updated: %d\n",
635*4882a593Smuzhiyun 		request_mgr_handle->axi_completed);
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	while (request_mgr_handle->axi_completed) {
638*4882a593Smuzhiyun 		do {
639*4882a593Smuzhiyun 			drvdata->irq |= cc_ioread(drvdata, CC_REG(HOST_IRR));
640*4882a593Smuzhiyun 			irq = (drvdata->irq & drvdata->comp_mask);
641*4882a593Smuzhiyun 			proc_completions(drvdata);
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 			/* At this point (after proc_completions()),
644*4882a593Smuzhiyun 			 * request_mgr_handle->axi_completed is 0.
645*4882a593Smuzhiyun 			 */
646*4882a593Smuzhiyun 			request_mgr_handle->axi_completed +=
647*4882a593Smuzhiyun 						cc_axi_comp_count(drvdata);
648*4882a593Smuzhiyun 		} while (request_mgr_handle->axi_completed > 0);
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 		cc_iowrite(drvdata, CC_REG(HOST_ICR), irq);
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 		request_mgr_handle->axi_completed += cc_axi_comp_count(drvdata);
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	/* after verifying that there is nothing to do,
656*4882a593Smuzhiyun 	 * unmask AXI completion interrupt
657*4882a593Smuzhiyun 	 */
658*4882a593Smuzhiyun 	cc_iowrite(drvdata, CC_REG(HOST_IMR),
659*4882a593Smuzhiyun 		   cc_ioread(drvdata, CC_REG(HOST_IMR)) & ~drvdata->comp_mask);
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	cc_proc_backlog(drvdata);
662*4882a593Smuzhiyun 	dev_dbg(dev, "Comp. handler done.\n");
663*4882a593Smuzhiyun }
664