xref: /freebsd/sys/dev/smartpqi/smartpqi_queue.c (revision eac7052fdebb90caf2f653e06187bdbca837b9c7)
1 /*-
2  * Copyright (c) 2018 Microsemi Corporation.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 /* $FreeBSD$ */
28 
29 #include "smartpqi_includes.h"
30 
31 /*
32  * Submit an admin IU to the adapter.
33  * Add interrupt support, if required
34  */
35 int pqisrc_submit_admin_req(pqisrc_softstate_t *softs,
36 			gen_adm_req_iu_t *req, gen_adm_resp_iu_t *resp)
37 {
38 	int ret = PQI_STATUS_SUCCESS;
39 	ob_queue_t *ob_q = &softs->admin_ob_queue;
40 	ib_queue_t *ib_q = &softs->admin_ib_queue;
41 	int tmo = PQISRC_ADMIN_CMD_RESP_TIMEOUT;
42 
43 	DBG_FUNC("IN\n");
44 
45 	req->header.iu_type =
46 		PQI_IU_TYPE_GENERAL_ADMIN_REQUEST;
47 	req->header.comp_feature = 0x00;
48 	req->header.iu_length = PQI_STANDARD_IU_LENGTH;
49 	req->res1 = 0;
50 	req->work = 0;
51 
52 	/* Get the tag */
53 	req->req_id = pqisrc_get_tag(&softs->taglist);
54 	if (INVALID_ELEM == req->req_id) {
55 		DBG_ERR("Tag not available0x%x\n",(uint16_t)req->req_id);
56 		ret = PQI_STATUS_FAILURE;
57 		goto err_out;
58 	}
59 	softs->rcb[req->req_id].tag = req->req_id;
60 
61 	/* Submit the command to the admin ib queue */
62 	ret = pqisrc_submit_cmnd(softs, ib_q, req);
63 	if (ret != PQI_STATUS_SUCCESS) {
64 		DBG_ERR("Unable to submit command\n");
65 		goto err_cmd;
66 	}
67 
68 	/* Wait for completion */
69 	COND_WAIT((*(ob_q->pi_virt_addr) != ob_q->ci_local), tmo);
70 	if (tmo <= 0) {
71 		DBG_ERR("Admin cmd timeout\n");
72 		DBG_ERR("tmo : %d\n",tmo);	\
73 		ret = PQI_STATUS_TIMEOUT;
74 		goto err_cmd;
75 	}
76 
77 	/* Copy the response */
78 	memcpy(resp, ob_q->array_virt_addr + (ob_q->ci_local * ob_q->elem_size),
79 					sizeof(gen_adm_resp_iu_t));
80 
81 	/* Update CI */
82 	ob_q->ci_local = (ob_q->ci_local + 1 ) %  ob_q->num_elem;
83 	PCI_MEM_PUT32(softs, ob_q->ci_register_abs,
84         ob_q->ci_register_offset, LE_32(ob_q->ci_local));
85 
86 	/* Validate the response data */
87 	ASSERT(req->fn_code == resp->fn_code);
88 	ASSERT(resp->header.iu_type == PQI_IU_TYPE_GENERAL_ADMIN_RESPONSE);
89 	ret = resp->status;
90 	if (ret)
91 		goto err_cmd;
92 
93 	os_reset_rcb(&softs->rcb[req->req_id]);
94 	pqisrc_put_tag(&softs->taglist,req->req_id);
95 	DBG_FUNC("OUT\n");
96 	return ret;
97 err_cmd:
98 	os_reset_rcb(&softs->rcb[req->req_id]);
99 	pqisrc_put_tag(&softs->taglist,req->req_id);
100 err_out:
101 	DBG_FUNC("failed OUT : %d\n", ret);
102 	return ret;
103 }
104 
105 /*
106  * Get the administration queue config parameters.
107  */
108 void pqisrc_get_admin_queue_config(pqisrc_softstate_t *softs)
109 {
110 	uint64_t val = 0;
111 
112 	val = LE_64(PCI_MEM_GET64(softs, &softs->pqi_reg->pqi_dev_adminq_cap, PQI_ADMINQ_CAP));
113 
114 	/* pqi_cap = (struct pqi_dev_adminq_cap *)&val;*/
115 	softs->admin_ib_queue.num_elem  =  val & 0xFF;
116 	softs->admin_ob_queue.num_elem  = (val & 0xFF00) >> 8;
117 	/* Note : size in unit of 16 byte s*/
118 	softs->admin_ib_queue.elem_size = ((val & 0xFF0000) >> 16) * 16;
119 	softs->admin_ob_queue.elem_size = ((val & 0xFF000000) >> 24) * 16;
120 
121 	DBG_FUNC(" softs->admin_ib_queue.num_elem : %d\n",
122 			softs->admin_ib_queue.num_elem);
123 	DBG_FUNC(" softs->admin_ib_queue.elem_size : %d\n",
124 			softs->admin_ib_queue.elem_size);
125 }
126 
127 /*
128  * Decide the no of elements in admin ib and ob queues.
129  */
130 void pqisrc_decide_admin_queue_config(pqisrc_softstate_t *softs)
131 {
132 	/* Determine  num elements in Admin IBQ  */
133 	softs->admin_ib_queue.num_elem = MIN(softs->admin_ib_queue.num_elem,
134 					PQISRC_MAX_ADMIN_IB_QUEUE_ELEM_NUM);
135 
136 	/* Determine  num elements in Admin OBQ  */
137 	softs->admin_ob_queue.num_elem = MIN(softs->admin_ob_queue.num_elem,
138 					PQISRC_MAX_ADMIN_OB_QUEUE_ELEM_NUM);
139 }
140 
141 /*
142  * Allocate DMA memory for admin queue and initialize.
143  */
144 int pqisrc_allocate_and_init_adminq(pqisrc_softstate_t *softs)
145 {
146 	uint32_t ib_array_size = 0;
147 	uint32_t ob_array_size = 0;
148 	uint32_t alloc_size = 0;
149 	char *virt_addr = NULL;
150 	dma_addr_t dma_addr = 0;
151 	int ret = PQI_STATUS_SUCCESS;
152 
153 	ib_array_size = (softs->admin_ib_queue.num_elem *
154 			softs->admin_ib_queue.elem_size);
155 
156 	ob_array_size = (softs->admin_ob_queue.num_elem *
157 			softs->admin_ob_queue.elem_size);
158 
159 	alloc_size = ib_array_size + ob_array_size +
160 			2 * sizeof(uint32_t) + PQI_ADDR_ALIGN_MASK_64 + 1; /* for IB CI and OB PI */
161 	/* Allocate memory for Admin Q */
162 	softs->admin_queue_dma_mem.tag = "admin_queue";
163 	softs->admin_queue_dma_mem.size = alloc_size;
164 	softs->admin_queue_dma_mem.align = PQI_ADMINQ_ELEM_ARRAY_ALIGN;
165 	ret = os_dma_mem_alloc(softs, &softs->admin_queue_dma_mem);
166 	if (ret) {
167 		DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret);
168 		goto err_out;
169 	}
170 
171 	/* Setup the address */
172 	virt_addr = softs->admin_queue_dma_mem.virt_addr;
173 	dma_addr = softs->admin_queue_dma_mem.dma_addr;
174 
175 	/* IB */
176 	softs->admin_ib_queue.q_id = 0;
177 	softs->admin_ib_queue.array_virt_addr = virt_addr;
178 	softs->admin_ib_queue.array_dma_addr = dma_addr;
179 	softs->admin_ib_queue.pi_local = 0;
180 	/* OB */
181 	softs->admin_ob_queue.q_id = 0;
182 	softs->admin_ob_queue.array_virt_addr = virt_addr + ib_array_size;
183 	softs->admin_ob_queue.array_dma_addr = dma_addr + ib_array_size;
184 	softs->admin_ob_queue.ci_local = 0;
185 
186 	/* IB CI */
187 	softs->admin_ib_queue.ci_virt_addr =
188 		(uint32_t*)((uint8_t*)softs->admin_ob_queue.array_virt_addr
189 				+ ob_array_size);
190 	softs->admin_ib_queue.ci_dma_addr =
191 		(dma_addr_t)((uint8_t*)softs->admin_ob_queue.array_dma_addr +
192 				ob_array_size);
193 
194 	/* OB PI */
195 	softs->admin_ob_queue.pi_virt_addr =
196 		(uint32_t*)((uint8_t*)(softs->admin_ib_queue.ci_virt_addr) +
197 		PQI_ADDR_ALIGN_MASK_64 + 1);
198 	softs->admin_ob_queue.pi_dma_addr =
199 		(dma_addr_t)((uint8_t*)(softs->admin_ib_queue.ci_dma_addr) +
200 		PQI_ADDR_ALIGN_MASK_64 + 1);
201 
202 	DBG_INIT("softs->admin_ib_queue.ci_dma_addr : %p,softs->admin_ob_queue.pi_dma_addr :%p\n",
203 				(void*)softs->admin_ib_queue.ci_dma_addr, (void*)softs->admin_ob_queue.pi_dma_addr );
204 
205 	/* Verify alignment */
206 	ASSERT(!(softs->admin_ib_queue.array_dma_addr &
207 				PQI_ADDR_ALIGN_MASK_64));
208 	ASSERT(!(softs->admin_ib_queue.ci_dma_addr &
209 				PQI_ADDR_ALIGN_MASK_64));
210 	ASSERT(!(softs->admin_ob_queue.array_dma_addr &
211 				PQI_ADDR_ALIGN_MASK_64));
212 	ASSERT(!(softs->admin_ob_queue.pi_dma_addr &
213 				PQI_ADDR_ALIGN_MASK_64));
214 
215 	DBG_FUNC("OUT\n");
216 	return ret;
217 
218 err_out:
219 	DBG_FUNC("failed OUT\n");
220 	return PQI_STATUS_FAILURE;
221 }
222 
223 /*
224  * Subroutine used to create (or) delete the admin queue requested.
225  */
226 int pqisrc_create_delete_adminq(pqisrc_softstate_t *softs,
227 					uint32_t cmd)
228 {
229 	int tmo = 0;
230 	int ret = PQI_STATUS_SUCCESS;
231 
232 	/* Create Admin Q pair writing to Admin Q config function reg */
233 
234 	PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG, LE_64(cmd));
235 
236 	if (cmd == PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR)
237 		tmo = PQISRC_ADMIN_QUEUE_CREATE_TIMEOUT;
238 	else
239 		tmo = PQISRC_ADMIN_QUEUE_DELETE_TIMEOUT;
240 
241 	/* Wait for completion */
242 	COND_WAIT((PCI_MEM_GET64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG) ==
243 				PQI_ADMIN_QUEUE_CONF_FUNC_STATUS_IDLE), tmo);
244 	if (tmo <= 0) {
245 		DBG_ERR("Unable to create/delete admin queue pair\n");
246 		ret = PQI_STATUS_TIMEOUT;
247 	}
248 
249 	return ret;
250 }
251 
252 /*
253  * Debug admin queue configuration params.
254  */
255 void pqisrc_print_adminq_config(pqisrc_softstate_t *softs)
256 {
257 	DBG_INFO(" softs->admin_ib_queue.array_dma_addr : %p\n",
258 		(void*)softs->admin_ib_queue.array_dma_addr);
259 	DBG_INFO(" softs->admin_ib_queue.array_virt_addr : %p\n",
260 		(void*)softs->admin_ib_queue.array_virt_addr);
261 	DBG_INFO(" softs->admin_ib_queue.num_elem : %d\n",
262 		softs->admin_ib_queue.num_elem);
263 	DBG_INFO(" softs->admin_ib_queue.elem_size : %d\n",
264 		softs->admin_ib_queue.elem_size);
265 	DBG_INFO(" softs->admin_ob_queue.array_dma_addr : %p\n",
266 		(void*)softs->admin_ob_queue.array_dma_addr);
267 	DBG_INFO(" softs->admin_ob_queue.array_virt_addr : %p\n",
268 		(void*)softs->admin_ob_queue.array_virt_addr);
269 	DBG_INFO(" softs->admin_ob_queue.num_elem : %d\n",
270 		softs->admin_ob_queue.num_elem);
271 	DBG_INFO(" softs->admin_ob_queue.elem_size : %d\n",
272 		softs->admin_ob_queue.elem_size);
273 	DBG_INFO(" softs->admin_ib_queue.pi_register_abs : %p\n",
274 		(void*)softs->admin_ib_queue.pi_register_abs);
275 	DBG_INFO(" softs->admin_ob_queue.ci_register_abs : %p\n",
276 		(void*)softs->admin_ob_queue.ci_register_abs);
277 }
278 
279 /*
280  * Function used to create an admin queue.
281  */
282 int pqisrc_create_admin_queue(pqisrc_softstate_t *softs)
283 {
284 	int ret = PQI_STATUS_SUCCESS;
285 	uint32_t admin_q_param = 0;
286 
287 	DBG_FUNC("IN\n");
288 
289 	/* Get admin queue details  - pqi2-r00a - table 24 */
290 	pqisrc_get_admin_queue_config(softs);
291 
292 	/* Decide admin Q config */
293 	pqisrc_decide_admin_queue_config(softs);
294 
295 	/* Allocate and init Admin Q pair */
296 	ret = pqisrc_allocate_and_init_adminq(softs);
297 	if (ret) {
298 		DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret);
299 		goto err_out;
300 	}
301 
302 	/* Write IB Q element array address */
303 	PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_elem_array_addr,
304         PQI_ADMIN_IBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ib_queue.array_dma_addr));
305 
306 	/* Write OB Q element array address */
307 	PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_elem_array_addr,
308         PQI_ADMIN_OBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ob_queue.array_dma_addr));
309 
310 	/* Write IB Q CI address */
311 	PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_ci_addr,
312         PQI_ADMIN_IBQ_CI_ADDR, LE_64(softs->admin_ib_queue.ci_dma_addr));
313 
314 	/* Write OB Q PI address */
315 	PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_pi_addr,
316         PQI_ADMIN_OBQ_PI_ADDR, LE_64(softs->admin_ob_queue.pi_dma_addr));
317 
318 	/* Write Admin Q params pqi-r200a table 36 */
319 
320 	admin_q_param = softs->admin_ib_queue.num_elem |
321 			 (softs->admin_ob_queue.num_elem  << 8)|
322 		        PQI_ADMIN_QUEUE_MSIX_DISABLE;
323 
324 	PCI_MEM_PUT32(softs, &softs->pqi_reg->admin_q_param,
325         PQI_ADMINQ_PARAM, LE_32(admin_q_param));
326 
327 	/* Submit cmd to create Admin Q pair */
328 	ret = pqisrc_create_delete_adminq(softs,
329 			PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR);
330 	if (ret) {
331 		DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret);
332 		goto err_q_create;
333 	}
334 
335 	/* Admin queue created, get ci,pi offset */
336     softs->admin_ib_queue.pi_register_offset =(PQISRC_PQI_REG_OFFSET +
337         PCI_MEM_GET64(softs, &softs->pqi_reg->admin_ibq_pi_offset, PQI_ADMIN_IBQ_PI_OFFSET));
338 
339     softs->admin_ib_queue.pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr +
340         softs->admin_ib_queue.pi_register_offset);
341 
342     softs->admin_ob_queue.ci_register_offset = (PQISRC_PQI_REG_OFFSET +
343         PCI_MEM_GET64(softs, &softs->pqi_reg->admin_obq_ci_offset, PQI_ADMIN_OBQ_CI_OFFSET));
344 
345     softs->admin_ob_queue.ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr +
346         softs->admin_ob_queue.ci_register_offset);
347 
348     os_strlcpy(softs->admin_ib_queue.lockname, "admin_ibqlock", LOCKNAME_SIZE);
349 
350     ret =OS_INIT_PQILOCK(softs, &softs->admin_ib_queue.lock,
351             softs->admin_ib_queue.lockname);
352     if(ret){
353         DBG_ERR("Admin spinlock initialization failed\n");
354         softs->admin_ib_queue.lockcreated = false;
355         goto err_lock;
356 	}
357     softs->admin_ib_queue.lockcreated = true;
358 
359 	/* Print admin q config details */
360 	pqisrc_print_adminq_config(softs);
361 
362 	DBG_FUNC("OUT\n");
363 	return ret;
364 
365 err_lock:
366 err_q_create:
367 	os_dma_mem_free(softs, &softs->admin_queue_dma_mem);
368 err_out:
369 	DBG_FUNC("failed OUT\n");
370 	return ret;
371 }
372 
373 /*
374  * Subroutine used to delete an operational queue.
375  */
376 int pqisrc_delete_op_queue(pqisrc_softstate_t *softs,
377 				uint32_t q_id, boolean_t ibq)
378 {
379 	int ret = PQI_STATUS_SUCCESS;
380 	/* Firmware doesn't support this now */
381 
382 #if 0
383 	gen_adm_req_iu_t admin_req;
384 	gen_adm_resp_iu_t admin_resp;
385 
386 	memset(&admin_req, 0, sizeof(admin_req));
387 	memset(&admin_resp, 0, sizeof(admin_resp));
388 
389 	DBG_FUNC("IN\n");
390 
391 	admin_req.req_type.create_op_iq.qid = q_id;
392 
393 	if (ibq)
394 		admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_IQ;
395 	else
396 		admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_OQ;
397 
398 	ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp);
399 
400 	DBG_FUNC("OUT\n");
401 #endif
402 	return ret;
403 }
404 
405 /*
406  * Function used to destroy the event queue.
407  */
408 void pqisrc_destroy_event_queue(pqisrc_softstate_t *softs)
409 {
410 	DBG_FUNC("IN\n");
411 
412 	if (softs->event_q.created == true) {
413 		int ret = PQI_STATUS_SUCCESS;
414 		ret = pqisrc_delete_op_queue(softs, softs->event_q.q_id, false);
415 		if (ret) {
416 			DBG_ERR("Failed to Delete Event Q %d\n", softs->event_q.q_id);
417 		}
418 		softs->event_q.created = false;
419 	}
420 
421 	/* Free the memory */
422 	os_dma_mem_free(softs, &softs->event_q_dma_mem);
423 
424 	DBG_FUNC("OUT\n");
425 }
426 
427 /*
428  * Function used to destroy operational ib queues.
429  */
430 void pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs)
431 {
432 	int ret = PQI_STATUS_SUCCESS;
433 	ib_queue_t *op_ib_q = NULL;
434 	int i;
435 
436 	DBG_FUNC("IN\n");
437 
438 	for (i = 0; i <  softs->num_op_raid_ibq; i++) {
439 		/* OP RAID IB Q */
440 		op_ib_q = &softs->op_raid_ib_q[i];
441 		if (op_ib_q->created == true) {
442 			ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, true);
443 			if (ret) {
444 				DBG_ERR("Failed to Delete Raid IB Q %d\n",op_ib_q->q_id);
445 			}
446 			op_ib_q->created = false;
447 		}
448 
449         if(op_ib_q->lockcreated==true){
450 		OS_UNINIT_PQILOCK(&op_ib_q->lock);
451             	op_ib_q->lockcreated = false;
452         }
453 
454 		/* OP AIO IB Q */
455 		op_ib_q = &softs->op_aio_ib_q[i];
456 		if (op_ib_q->created == true) {
457 			ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, true);
458 			if (ret) {
459 				DBG_ERR("Failed to Delete AIO IB Q %d\n",op_ib_q->q_id);
460 			}
461 			op_ib_q->created = false;
462 		}
463 
464         if(op_ib_q->lockcreated==true){
465 		OS_UNINIT_PQILOCK(&op_ib_q->lock);
466 		op_ib_q->lockcreated = false;
467         }
468 	}
469 
470 	/* Free the memory */
471 	os_dma_mem_free(softs, &softs->op_ibq_dma_mem);
472 	DBG_FUNC("OUT\n");
473 }
474 
475 /*
476  * Function used to destroy operational ob queues.
477  */
478 void pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs)
479 {
480 	int ret = PQI_STATUS_SUCCESS;
481 	int i;
482 
483 	DBG_FUNC("IN\n");
484 
485 	for (i = 0; i <  softs->num_op_obq; i++) {
486 		ob_queue_t *op_ob_q = NULL;
487 		op_ob_q = &softs->op_ob_q[i];
488 		if (op_ob_q->created == true) {
489 			ret = pqisrc_delete_op_queue(softs, op_ob_q->q_id, false);
490 			if (ret) {
491 				DBG_ERR("Failed to Delete OB Q %d\n",op_ob_q->q_id);
492 			}
493 			op_ob_q->created = false;
494 		}
495 	}
496 
497 	/* Free the memory */
498 	os_dma_mem_free(softs, &softs->op_obq_dma_mem);
499 	DBG_FUNC("OUT\n");
500 }
501 
502 /*
503  * Function used to destroy an admin queue.
504  */
505 int pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs)
506 {
507 	int ret = PQI_STATUS_SUCCESS;
508 
509 	DBG_FUNC("IN\n");
510 #if 0
511 	ret = pqisrc_create_delete_adminq(softs,
512 				PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR);
513 #endif
514 	os_dma_mem_free(softs, &softs->admin_queue_dma_mem);
515 
516 	DBG_FUNC("OUT\n");
517 	return ret;
518 }
519 
520 /*
521  * Function used to change operational ib queue properties.
522  */
523 int pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs,
524 			ib_queue_t *op_ib_q, uint32_t prop)
525 {
526 	int ret = PQI_STATUS_SUCCESS;
527 	gen_adm_req_iu_t admin_req;
528 	gen_adm_resp_iu_t admin_resp;
529 
530 	memset(&admin_req, 0, sizeof(admin_req));
531 	memset(&admin_resp, 0, sizeof(admin_resp));
532 
533 	DBG_FUNC("IN\n");
534 
535 	admin_req.fn_code = PQI_FUNCTION_CHANGE_OPERATIONAL_IQ_PROP;
536 	admin_req.req_type.change_op_iq_prop.qid = op_ib_q->q_id;
537 	admin_req.req_type.change_op_iq_prop.vend_specific = prop;
538 
539 	ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp);
540 
541 	DBG_FUNC("OUT\n");
542 	return ret;
543 }
544 
545 /*
546  * Function used to create an operational ob queue.
547  */
548 int pqisrc_create_op_obq(pqisrc_softstate_t *softs,
549 			ob_queue_t *op_ob_q)
550 {
551 	int ret = PQI_STATUS_SUCCESS;
552 	gen_adm_req_iu_t admin_req;
553 	gen_adm_resp_iu_t admin_resp;
554 
555 	DBG_FUNC("IN\n");
556 
557 	memset(&admin_req, 0, sizeof(admin_req));
558 	memset(&admin_resp, 0, sizeof(admin_resp));
559 
560 	admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_OQ;
561 	admin_req.req_type.create_op_oq.qid = op_ob_q->q_id;
562 	admin_req.req_type.create_op_oq.intr_msg_num =  op_ob_q->intr_msg_num;
563 	admin_req.req_type.create_op_oq.elem_arr_addr = op_ob_q->array_dma_addr;
564 	admin_req.req_type.create_op_oq.ob_pi_addr = op_ob_q->pi_dma_addr;
565 	admin_req.req_type.create_op_oq.num_elem =  op_ob_q->num_elem;
566 	admin_req.req_type.create_op_oq.elem_len = op_ob_q->elem_size / 16;
567 
568 	DBG_INFO("admin_req.req_type.create_op_oq.qid : %x\n",admin_req.req_type.create_op_oq.qid);
569 	DBG_INFO("admin_req.req_type.create_op_oq.intr_msg_num  : %x\n", admin_req.req_type.create_op_oq.intr_msg_num );
570 
571 	ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp);
572 	if( PQI_STATUS_SUCCESS == ret) {
573 		op_ob_q->ci_register_offset = (PQISRC_PQI_REG_OFFSET +
574 				admin_resp.resp_type.create_op_oq.ci_offset);
575 		op_ob_q->ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr +
576 				op_ob_q->ci_register_offset);
577     	} else {
578 		int i = 0;
579 		DBG_WARN("Error Status Descriptors\n");
580 		for(i = 0; i < 4;i++)
581 			DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]);
582 	}
583 
584 	DBG_FUNC("OUT ret : %d\n", ret);
585 
586 	return ret;
587 }
588 
589 /*
590  * Function used to create an operational ib queue.
591  */
592 int pqisrc_create_op_ibq(pqisrc_softstate_t *softs,
593 			ib_queue_t *op_ib_q)
594 {
595 	int ret = PQI_STATUS_SUCCESS;
596 	gen_adm_req_iu_t admin_req;
597 	gen_adm_resp_iu_t admin_resp;
598 
599 	DBG_FUNC("IN\n");
600 
601 	memset(&admin_req, 0, sizeof(admin_req));
602 	memset(&admin_resp, 0, sizeof(admin_resp));
603 
604 	admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_IQ;
605 	admin_req.req_type.create_op_iq.qid = op_ib_q->q_id;
606 	admin_req.req_type.create_op_iq.elem_arr_addr = op_ib_q->array_dma_addr;
607 	admin_req.req_type.create_op_iq.iq_ci_addr = op_ib_q->ci_dma_addr;
608 	admin_req.req_type.create_op_iq.num_elem =  op_ib_q->num_elem;
609 	admin_req.req_type.create_op_iq.elem_len = op_ib_q->elem_size / 16;
610 
611 	ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp);
612 
613 	if( PQI_STATUS_SUCCESS == ret) {
614 		op_ib_q->pi_register_offset =(PQISRC_PQI_REG_OFFSET +
615 				admin_resp.resp_type.create_op_iq.pi_offset);
616 
617 		op_ib_q->pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr +
618 				op_ib_q->pi_register_offset);
619 	} else {
620 		int i = 0;
621 		DBG_WARN("Error Status Decsriptors\n");
622 		for(i = 0; i < 4;i++)
623 			DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]);
624 	}
625 
626 	DBG_FUNC("OUT ret : %d\n", ret);
627 	return ret;
628 }
629 
630 /*
631  * subroutine used to create an operational ib queue for AIO.
632  */
633 int pqisrc_create_op_aio_ibq(pqisrc_softstate_t *softs,
634 			ib_queue_t *op_aio_ib_q)
635 {
636 	int ret = PQI_STATUS_SUCCESS;
637 
638 	DBG_FUNC("IN\n");
639 
640 	ret = pqisrc_create_op_ibq(softs,op_aio_ib_q);
641 	if ( PQI_STATUS_SUCCESS == ret)
642 		ret = pqisrc_change_op_ibq_queue_prop(softs,
643 					op_aio_ib_q, PQI_CHANGE_OP_IQ_PROP_ASSIGN_AIO);
644 
645 	DBG_FUNC("OUT ret : %d\n", ret);
646 	return ret;
647 }
648 
649 /*
650  * subroutine used to create an operational ib queue for RAID.
651  */
652 int pqisrc_create_op_raid_ibq(pqisrc_softstate_t *softs,
653 			ib_queue_t *op_raid_ib_q)
654 {
655 	int ret = PQI_STATUS_SUCCESS;
656 
657 	DBG_FUNC("IN\n");
658 
659 	ret = pqisrc_create_op_ibq(softs,op_raid_ib_q);
660 
661 	DBG_FUNC("OUT\n");
662 	return ret;
663 }
664 
665 /*
666  * Allocate and create an event queue to process supported events.
667  */
668 int pqisrc_alloc_and_create_event_queue(pqisrc_softstate_t *softs)
669 {
670 	int ret = PQI_STATUS_SUCCESS;
671 	uint32_t alloc_size = 0;
672 	uint32_t num_elem;
673 	char *virt_addr = NULL;
674 	dma_addr_t dma_addr = 0;
675 	uint32_t event_q_pi_dma_start_offset = 0;
676 	uint32_t event_q_pi_virt_start_offset = 0;
677 	char *event_q_pi_virt_start_addr = NULL;
678 	ob_queue_t *event_q = NULL;
679 
680 	DBG_FUNC("IN\n");
681 
682 	/*
683 	 * Calculate memory requirements.
684 	 * If event queue is shared for IO response, number of
685 	 * elements in event queue depends on num elements in OP OB Q
686 	 * also. Since event queue element size (32) is more than IO
687 	 * response size , event queue element size need not be checked
688 	 * for queue size calculation.
689 	 */
690 #ifdef SHARE_EVENT_QUEUE_FOR_IO
691 	num_elem = MIN(softs->num_elem_per_op_obq, PQISRC_NUM_EVENT_Q_ELEM);
692 #else
693 	num_elem = PQISRC_NUM_EVENT_Q_ELEM;
694 #endif
695 
696 	alloc_size = num_elem *  PQISRC_EVENT_Q_ELEM_SIZE;
697 	event_q_pi_dma_start_offset = alloc_size;
698 	event_q_pi_virt_start_offset = alloc_size;
699 	alloc_size += sizeof(uint32_t); /*For IBQ CI*/
700 
701 	/* Allocate memory for event queues */
702 	softs->event_q_dma_mem.tag = "event_queue";
703 	softs->event_q_dma_mem.size = alloc_size;
704 	softs->event_q_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN;
705 	ret = os_dma_mem_alloc(softs, &softs->event_q_dma_mem);
706 	if (ret) {
707 		DBG_ERR("Failed to Allocate Event Q ret : %d\n"
708 				, ret);
709 		goto err_out;
710 	}
711 
712 	/* Set up the address */
713 	virt_addr = softs->event_q_dma_mem.virt_addr;
714 	dma_addr = softs->event_q_dma_mem.dma_addr;
715 	event_q_pi_dma_start_offset += dma_addr;
716 	event_q_pi_virt_start_addr = virt_addr + event_q_pi_virt_start_offset;
717 
718 	event_q = &softs->event_q;
719 	ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64));
720 	FILL_QUEUE_ARRAY_ADDR(event_q,virt_addr,dma_addr);
721 	event_q->q_id = PQI_OP_EVENT_QUEUE_ID;
722 	event_q->num_elem = num_elem;
723 	event_q->elem_size = PQISRC_EVENT_Q_ELEM_SIZE;
724 	event_q->pi_dma_addr = event_q_pi_dma_start_offset;
725 	event_q->pi_virt_addr = (uint32_t *)event_q_pi_virt_start_addr;
726 	event_q->intr_msg_num = 0; /* vector zero for event */
727 	ASSERT(!(event_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4));
728 
729 	ret = pqisrc_create_op_obq(softs,event_q);
730 	if (ret) {
731 		DBG_ERR("Failed to Create EventQ %d\n",event_q->q_id);
732 		goto err_out_create;
733 	}
734 	event_q->created  = true;
735 
736 	DBG_FUNC("OUT\n");
737 	return ret;
738 
739 err_out_create:
740 	pqisrc_destroy_event_queue(softs);
741 err_out:
742 	DBG_FUNC("OUT failed %d\n", ret);
743 	return PQI_STATUS_FAILURE;
744 }
745 
746 /*
747  * Allocate DMA memory and create operational ib queues.
748  */
749 int pqisrc_alloc_and_create_ib_queues(pqisrc_softstate_t *softs)
750 {
751 	int ret = PQI_STATUS_SUCCESS;
752 	uint32_t alloc_size = 0;
753 	char *virt_addr = NULL;
754 	dma_addr_t dma_addr = 0;
755 	uint32_t ibq_size = 0;
756 	uint32_t ib_ci_dma_start_offset = 0;
757 	char *ib_ci_virt_start_addr = NULL;
758 	uint32_t ib_ci_virt_start_offset = 0;
759 	uint32_t ibq_id = PQI_MIN_OP_IB_QUEUE_ID;
760 	ib_queue_t *op_ib_q = NULL;
761 	uint32_t num_op_ibq = softs->num_op_raid_ibq +
762 				softs->num_op_aio_ibq;
763 	int i = 0;
764 
765 	DBG_FUNC("IN\n");
766 
767 	/* Calculate memory requirements */
768 	ibq_size = softs->num_elem_per_op_ibq *  softs->ibq_elem_size;
769 	alloc_size =  num_op_ibq * ibq_size;
770 	/* CI indexes starts after Queue element array */
771 	ib_ci_dma_start_offset = alloc_size;
772 	ib_ci_virt_start_offset = alloc_size;
773 	alloc_size += num_op_ibq * sizeof(uint32_t); /*For IBQ CI*/
774 
775 	/* Allocate memory for IB queues */
776 	softs->op_ibq_dma_mem.tag = "op_ib_queue";
777 	softs->op_ibq_dma_mem.size = alloc_size;
778 	softs->op_ibq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN;
779 	ret = os_dma_mem_alloc(softs, &softs->op_ibq_dma_mem);
780 	if (ret) {
781 		DBG_ERR("Failed to Allocate Operational IBQ memory ret : %d\n",
782 						ret);
783 		goto err_out;
784 	}
785 
786 	/* Set up the address */
787 	virt_addr = softs->op_ibq_dma_mem.virt_addr;
788 	dma_addr = softs->op_ibq_dma_mem.dma_addr;
789 	ib_ci_dma_start_offset += dma_addr;
790 	ib_ci_virt_start_addr = virt_addr + ib_ci_virt_start_offset;
791 
792 	ASSERT(softs->num_op_raid_ibq == softs->num_op_aio_ibq);
793 
794 	for (i = 0; i <  softs->num_op_raid_ibq; i++) {
795 		/* OP RAID IB Q */
796 		op_ib_q = &softs->op_raid_ib_q[i];
797 		ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64));
798 		FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr);
799 		op_ib_q->q_id = ibq_id++;
800 
801         	snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "raid_ibqlock%d", i);
802 		ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname);
803         	if(ret){
804             		DBG_ERR("raid_ibqlock %d init failed\n", i);
805             		op_ib_q->lockcreated = false;
806             		goto err_lock;
807 		}
808         	op_ib_q->lockcreated = true;
809         	op_ib_q->num_elem = softs->num_elem_per_op_ibq;
810 		op_ib_q->elem_size = softs->ibq_elem_size;
811 		op_ib_q->ci_dma_addr = ib_ci_dma_start_offset +
812 					(2 * i * sizeof(uint32_t));
813 		op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr +
814 					(2 * i * sizeof(uint32_t)));
815 		ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4));
816 		ret = pqisrc_create_op_raid_ibq(softs, op_ib_q);
817 		if (ret) {
818 			DBG_ERR("[ %s ] Failed to Create OP Raid IBQ %d\n",
819 					__func__, op_ib_q->q_id);
820 			goto err_out_create;
821 		}
822 		op_ib_q->created  = true;
823 
824 		/* OP AIO IB Q */
825 		virt_addr += ibq_size;
826 		dma_addr += ibq_size;
827 		op_ib_q = &softs->op_aio_ib_q[i];
828 		ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64));
829 		FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr);
830 		op_ib_q->q_id = ibq_id++;
831         	snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "aio_ibqlock%d", i);
832 		ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname);
833         	if(ret){
834             		DBG_ERR("aio_ibqlock %d init failed\n", i);
835             		op_ib_q->lockcreated = false;
836             		goto err_lock;
837         	}
838         	op_ib_q->lockcreated = true;
839      		op_ib_q->num_elem = softs->num_elem_per_op_ibq;
840 		op_ib_q->elem_size = softs->ibq_elem_size;
841 		op_ib_q->ci_dma_addr = ib_ci_dma_start_offset +
842 					(((2 * i) + 1) * sizeof(uint32_t));
843 		op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr +
844 					(((2 * i) + 1) * sizeof(uint32_t)));
845 		ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4));
846 		ret = pqisrc_create_op_aio_ibq(softs, op_ib_q);
847 		if (ret) {
848 			DBG_ERR("Failed to Create OP AIO IBQ %d\n",op_ib_q->q_id);
849 			goto err_out_create;
850 		}
851 		op_ib_q->created  = true;
852 
853 		virt_addr += ibq_size;
854 		dma_addr += ibq_size;
855 	}
856 
857 	DBG_FUNC("OUT\n");
858 	return ret;
859 
860 err_lock:
861 err_out_create:
862 	pqisrc_destroy_op_ib_queues(softs);
863 err_out:
864 	DBG_FUNC("OUT failed %d\n", ret);
865 	return PQI_STATUS_FAILURE;
866 }
867 
868 /*
869  * Allocate DMA memory and create operational ob queues.
870  */
871 int pqisrc_alloc_and_create_ob_queues(pqisrc_softstate_t *softs)
872 {
873 	int ret = PQI_STATUS_SUCCESS;
874 	uint32_t alloc_size = 0;
875 	char *virt_addr = NULL;
876 	dma_addr_t dma_addr = 0;
877 	uint32_t obq_size = 0;
878 	uint32_t ob_pi_dma_start_offset = 0;
879 	uint32_t ob_pi_virt_start_offset = 0;
880 	char *ob_pi_virt_start_addr = NULL;
881 	uint32_t obq_id = PQI_MIN_OP_OB_QUEUE_ID;
882 	ob_queue_t *op_ob_q = NULL;
883  	uint32_t num_op_obq = softs->num_op_obq;
884 	int i = 0;
885 
886 	DBG_FUNC("IN\n");
887 
888 	/*
889 	 * OB Q element array should be 64 byte aligned.
890 	 * So the number of elements in OB Q should be multiple
891 	 * of 4, so that OB Queue element size (16) * num elements
892 	 * will be multiple of 64.
893 	 */
894 
895 	ALIGN_BOUNDARY(softs->num_elem_per_op_obq, 4);
896 	obq_size = softs->num_elem_per_op_obq *  softs->obq_elem_size;
897 	alloc_size += num_op_obq * obq_size;
898 	/* PI indexes starts after Queue element array */
899 	ob_pi_dma_start_offset = alloc_size;
900 	ob_pi_virt_start_offset = alloc_size;
901 	alloc_size += num_op_obq * sizeof(uint32_t); /*For OBQ PI*/
902 
903 	/* Allocate memory for OB queues */
904 	softs->op_obq_dma_mem.tag = "op_ob_queue";
905 	softs->op_obq_dma_mem.size = alloc_size;
906 	softs->op_obq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN;
907 	ret = os_dma_mem_alloc(softs, &softs->op_obq_dma_mem);
908 	if (ret) {
909 		DBG_ERR("Failed to Allocate Operational OBQ memory ret : %d\n",
910 						ret);
911 		goto err_out;
912 	}
913 
914 	/* Set up the address */
915 	virt_addr = softs->op_obq_dma_mem.virt_addr;
916 	dma_addr = softs->op_obq_dma_mem.dma_addr;
917 	ob_pi_dma_start_offset += dma_addr;
918 	ob_pi_virt_start_addr = virt_addr + ob_pi_virt_start_offset;
919 
920 	DBG_INFO("softs->num_op_obq %d\n",softs->num_op_obq);
921 
922 	for (i = 0; i <  softs->num_op_obq; i++) {
923 		op_ob_q = &softs->op_ob_q[i];
924 		ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64));
925 		FILL_QUEUE_ARRAY_ADDR(op_ob_q,virt_addr,dma_addr);
926 		op_ob_q->q_id = obq_id++;
927 		if(softs->share_opq_and_eventq == true)
928 			op_ob_q->intr_msg_num = i;
929 		else
930 			op_ob_q->intr_msg_num = i + 1; /* msg num zero for event */
931 		op_ob_q->num_elem = softs->num_elem_per_op_obq;
932 		op_ob_q->elem_size = softs->obq_elem_size;
933 		op_ob_q->pi_dma_addr = ob_pi_dma_start_offset +
934 					(i * sizeof(uint32_t));
935 		op_ob_q->pi_virt_addr = (uint32_t*)(ob_pi_virt_start_addr +
936 					(i * sizeof(uint32_t)));
937 		ASSERT(!(op_ob_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4));
938 
939 		ret = pqisrc_create_op_obq(softs,op_ob_q);
940 		if (ret) {
941 			DBG_ERR("Failed to Create OP OBQ %d\n",op_ob_q->q_id);
942 			goto err_out_create;
943 		}
944 		op_ob_q->created  = true;
945 		virt_addr += obq_size;
946 		dma_addr += obq_size;
947 	}
948 
949 	DBG_FUNC("OUT\n");
950 	return ret;
951 
952 err_out_create:
953 	pqisrc_destroy_op_ob_queues(softs);
954 err_out:
955 	DBG_FUNC("OUT failed %d\n", ret);
956 	return PQI_STATUS_FAILURE;
957 }
958 
959 /*
960  * Function used to create operational queues for the adapter.
961  */
962 int pqisrc_create_op_queues(pqisrc_softstate_t *softs)
963 {
964 	int ret = PQI_STATUS_SUCCESS;
965 
966 	DBG_FUNC("IN\n");
967 
968 	/* Create Operational IB queues */
969 	ret = pqisrc_alloc_and_create_ib_queues(softs);
970 	if (ret)
971 		goto err_out;
972 	/* Create Operational OB queues */
973 	ret = pqisrc_alloc_and_create_ob_queues(softs);
974 	if (ret)
975 		goto err_out_obq;
976 
977 	/* Create Event queue */
978 	ret = pqisrc_alloc_and_create_event_queue(softs);
979 	if (ret)
980 		goto err_out_eventq;
981 
982 	DBG_FUNC("OUT\n");
983 	return ret;
984 err_out_eventq:
985 	pqisrc_destroy_op_ob_queues(softs);
986 err_out_obq:
987 	pqisrc_destroy_op_ib_queues(softs);
988 err_out:
989 	DBG_FUNC("OUT failed %d\n", ret);
990 	return PQI_STATUS_FAILURE;
991 }
992