Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/smartpqi/smartpqi_queue.c
/*- | /*- | ||||
* Copyright (c) 2018 Microsemi Corporation. | * Copyright (c) 2016-2019 Microsemi Corporation. | ||||
* Copyright (c) 2020 Microchip Technology Inc. and it's subsidiaries. | |||||
* | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
Context not available. | |||||
ob_queue_t *ob_q = &softs->admin_ob_queue; | ob_queue_t *ob_q = &softs->admin_ob_queue; | ||||
ib_queue_t *ib_q = &softs->admin_ib_queue; | ib_queue_t *ib_q = &softs->admin_ib_queue; | ||||
int tmo = PQISRC_ADMIN_CMD_RESP_TIMEOUT; | int tmo = PQISRC_ADMIN_CMD_RESP_TIMEOUT; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
req->header.iu_type = | req->header.iu_type = | ||||
Context not available. | |||||
req->header.iu_length = PQI_STANDARD_IU_LENGTH; | req->header.iu_length = PQI_STANDARD_IU_LENGTH; | ||||
req->res1 = 0; | req->res1 = 0; | ||||
req->work = 0; | req->work = 0; | ||||
/* Get the tag */ | /* Get the tag */ | ||||
req->req_id = pqisrc_get_tag(&softs->taglist); | req->req_id = pqisrc_get_tag(&softs->taglist); | ||||
if (INVALID_ELEM == req->req_id) { | if (INVALID_ELEM == req->req_id) { | ||||
Context not available. | |||||
goto err_out; | goto err_out; | ||||
} | } | ||||
softs->rcb[req->req_id].tag = req->req_id; | softs->rcb[req->req_id].tag = req->req_id; | ||||
/* Submit the command to the admin ib queue */ | /* Submit the command to the admin ib queue */ | ||||
ret = pqisrc_submit_cmnd(softs, ib_q, req); | ret = pqisrc_submit_cmnd(softs, ib_q, req); | ||||
if (ret != PQI_STATUS_SUCCESS) { | if (ret != PQI_STATUS_SUCCESS) { | ||||
Context not available. | |||||
if (tmo <= 0) { | if (tmo <= 0) { | ||||
DBG_ERR("Admin cmd timeout\n"); | DBG_ERR("Admin cmd timeout\n"); | ||||
DBG_ERR("tmo : %d\n",tmo); \ | DBG_ERR("tmo : %d\n",tmo); \ | ||||
/* TODO : PQI device status and error register and report */ | |||||
ret = PQI_STATUS_TIMEOUT; | ret = PQI_STATUS_TIMEOUT; | ||||
goto err_cmd; | goto err_cmd; | ||||
} | } | ||||
/* Copy the response */ | /* Copy the response */ | ||||
memcpy(resp, ob_q->array_virt_addr + (ob_q->ci_local * ob_q->elem_size), | memcpy(resp, ob_q->array_virt_addr + (ob_q->ci_local * ob_q->elem_size), | ||||
sizeof(gen_adm_resp_iu_t)); | sizeof(gen_adm_resp_iu_t)); | ||||
/* Update CI */ | /* Update CI */ | ||||
ob_q->ci_local = (ob_q->ci_local + 1 ) % ob_q->num_elem; | ob_q->ci_local = (ob_q->ci_local + 1 ) % ob_q->num_elem; | ||||
PCI_MEM_PUT32(softs, ob_q->ci_register_abs, | PCI_MEM_PUT32(softs, ob_q->ci_register_abs, | ||||
ob_q->ci_register_offset, LE_32(ob_q->ci_local)); | ob_q->ci_register_offset, LE_32(ob_q->ci_local)); | ||||
/* Validate the response data */ | /* Validate the response data */ | ||||
ASSERT(req->fn_code == resp->fn_code); | ASSERT(req->fn_code == resp->fn_code); | ||||
ASSERT(resp->header.iu_type == PQI_IU_TYPE_GENERAL_ADMIN_RESPONSE); | ASSERT(resp->header.iu_type == PQI_IU_TYPE_GENERAL_ADMIN_RESPONSE); | ||||
Context not available. | |||||
/* Note : size in unit of 16 byte s*/ | /* Note : size in unit of 16 byte s*/ | ||||
softs->admin_ib_queue.elem_size = ((val & 0xFF0000) >> 16) * 16; | softs->admin_ib_queue.elem_size = ((val & 0xFF0000) >> 16) * 16; | ||||
softs->admin_ob_queue.elem_size = ((val & 0xFF000000) >> 24) * 16; | softs->admin_ob_queue.elem_size = ((val & 0xFF000000) >> 24) * 16; | ||||
DBG_FUNC(" softs->admin_ib_queue.num_elem : %d\n", | DBG_FUNC(" softs->admin_ib_queue.num_elem : %d\n", | ||||
softs->admin_ib_queue.num_elem); | softs->admin_ib_queue.num_elem); | ||||
DBG_FUNC(" softs->admin_ib_queue.elem_size : %d\n", | DBG_FUNC(" softs->admin_ib_queue.elem_size : %d\n", | ||||
Context not available. | |||||
} | } | ||||
/* | /* | ||||
* Decide the no of elements in admin ib and ob queues. | * Decide the no of elements in admin ib and ob queues. | ||||
*/ | */ | ||||
void pqisrc_decide_admin_queue_config(pqisrc_softstate_t *softs) | void pqisrc_decide_admin_queue_config(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
/* Determine num elements in Admin IBQ */ | /* Determine num elements in Admin IBQ */ | ||||
softs->admin_ib_queue.num_elem = MIN(softs->admin_ib_queue.num_elem, | softs->admin_ib_queue.num_elem = MIN(softs->admin_ib_queue.num_elem, | ||||
PQISRC_MAX_ADMIN_IB_QUEUE_ELEM_NUM); | PQISRC_MAX_ADMIN_IB_QUEUE_ELEM_NUM); | ||||
/* Determine num elements in Admin OBQ */ | /* Determine num elements in Admin OBQ */ | ||||
softs->admin_ob_queue.num_elem = MIN(softs->admin_ob_queue.num_elem, | softs->admin_ob_queue.num_elem = MIN(softs->admin_ob_queue.num_elem, | ||||
PQISRC_MAX_ADMIN_OB_QUEUE_ELEM_NUM); | PQISRC_MAX_ADMIN_OB_QUEUE_ELEM_NUM); | ||||
Context not available. | |||||
ib_array_size = (softs->admin_ib_queue.num_elem * | ib_array_size = (softs->admin_ib_queue.num_elem * | ||||
softs->admin_ib_queue.elem_size); | softs->admin_ib_queue.elem_size); | ||||
ob_array_size = (softs->admin_ob_queue.num_elem * | ob_array_size = (softs->admin_ob_queue.num_elem * | ||||
softs->admin_ob_queue.elem_size); | softs->admin_ob_queue.elem_size); | ||||
Context not available. | |||||
softs->admin_ob_queue.array_virt_addr = virt_addr + ib_array_size; | softs->admin_ob_queue.array_virt_addr = virt_addr + ib_array_size; | ||||
softs->admin_ob_queue.array_dma_addr = dma_addr + ib_array_size; | softs->admin_ob_queue.array_dma_addr = dma_addr + ib_array_size; | ||||
softs->admin_ob_queue.ci_local = 0; | softs->admin_ob_queue.ci_local = 0; | ||||
/* IB CI */ | /* IB CI */ | ||||
softs->admin_ib_queue.ci_virt_addr = | softs->admin_ib_queue.ci_virt_addr = | ||||
(uint32_t*)((uint8_t*)softs->admin_ob_queue.array_virt_addr | (uint32_t*)((uint8_t*)softs->admin_ob_queue.array_virt_addr | ||||
+ ob_array_size); | + ob_array_size); | ||||
softs->admin_ib_queue.ci_dma_addr = | softs->admin_ib_queue.ci_dma_addr = | ||||
(dma_addr_t)((uint8_t*)softs->admin_ob_queue.array_dma_addr + | (dma_addr_t)((uint8_t*)softs->admin_ob_queue.array_dma_addr + | ||||
ob_array_size); | ob_array_size); | ||||
/* OB PI */ | /* OB PI */ | ||||
softs->admin_ob_queue.pi_virt_addr = | softs->admin_ob_queue.pi_virt_addr = | ||||
(uint32_t*)((uint8_t*)(softs->admin_ib_queue.ci_virt_addr) + | (uint32_t*)((uint8_t*)(softs->admin_ib_queue.ci_virt_addr) + | ||||
PQI_ADDR_ALIGN_MASK_64 + 1); | PQI_ADDR_ALIGN_MASK_64 + 1); | ||||
softs->admin_ob_queue.pi_dma_addr = | softs->admin_ob_queue.pi_dma_addr = | ||||
(dma_addr_t)((uint8_t*)(softs->admin_ib_queue.ci_dma_addr) + | (dma_addr_t)((uint8_t*)(softs->admin_ib_queue.ci_dma_addr) + | ||||
PQI_ADDR_ALIGN_MASK_64 + 1); | PQI_ADDR_ALIGN_MASK_64 + 1); | ||||
DBG_INIT("softs->admin_ib_queue.ci_dma_addr : %p,softs->admin_ob_queue.pi_dma_addr :%p\n", | DBG_INIT("softs->admin_ib_queue.ci_dma_addr : %p,softs->admin_ob_queue.pi_dma_addr :%p\n", | ||||
Context not available. | |||||
/* Create Admin Q pair writing to Admin Q config function reg */ | /* Create Admin Q pair writing to Admin Q config function reg */ | ||||
PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG, LE_64(cmd)); | PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG, LE_64(cmd)); | ||||
if (cmd == PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR) | if (cmd == PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR) | ||||
tmo = PQISRC_ADMIN_QUEUE_CREATE_TIMEOUT; | tmo = PQISRC_ADMIN_QUEUE_CREATE_TIMEOUT; | ||||
else | else | ||||
tmo = PQISRC_ADMIN_QUEUE_DELETE_TIMEOUT; | tmo = PQISRC_ADMIN_QUEUE_DELETE_TIMEOUT; | ||||
/* Wait for completion */ | /* Wait for completion */ | ||||
COND_WAIT((PCI_MEM_GET64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG) == | COND_WAIT((PCI_MEM_GET64(softs, &softs->pqi_reg->admin_q_config, PQI_ADMINQ_CONFIG) == | ||||
PQI_ADMIN_QUEUE_CONF_FUNC_STATUS_IDLE), tmo); | PQI_ADMIN_QUEUE_CONF_FUNC_STATUS_IDLE), tmo); | ||||
if (tmo <= 0) { | if (tmo <= 0) { | ||||
DBG_ERR("Unable to create/delete admin queue pair\n"); | DBG_ERR("Unable to create/delete admin queue pair\n"); | ||||
/* TODO : PQI device status and error register and report */ | |||||
ret = PQI_STATUS_TIMEOUT; | ret = PQI_STATUS_TIMEOUT; | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* Debug admin queue configuration params. | * Debug admin queue configuration params. | ||||
Context not available. | |||||
DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret); | DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* Write IB Q element array address */ | /* Write IB Q element array address */ | ||||
PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_elem_array_addr, | PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_elem_array_addr, | ||||
PQI_ADMIN_IBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ib_queue.array_dma_addr)); | PQI_ADMIN_IBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ib_queue.array_dma_addr)); | ||||
/* Write OB Q element array address */ | /* Write OB Q element array address */ | ||||
PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_elem_array_addr, | PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_elem_array_addr, | ||||
PQI_ADMIN_OBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ob_queue.array_dma_addr)); | PQI_ADMIN_OBQ_ELEM_ARRAY_ADDR, LE_64(softs->admin_ob_queue.array_dma_addr)); | ||||
/* Write IB Q CI address */ | /* Write IB Q CI address */ | ||||
PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_ci_addr, | PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_ibq_ci_addr, | ||||
PQI_ADMIN_IBQ_CI_ADDR, LE_64(softs->admin_ib_queue.ci_dma_addr)); | PQI_ADMIN_IBQ_CI_ADDR, LE_64(softs->admin_ib_queue.ci_dma_addr)); | ||||
/* Write OB Q PI address */ | /* Write OB Q PI address */ | ||||
PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_pi_addr, | PCI_MEM_PUT64(softs, &softs->pqi_reg->admin_obq_pi_addr, | ||||
PQI_ADMIN_OBQ_PI_ADDR, LE_64(softs->admin_ob_queue.pi_dma_addr)); | PQI_ADMIN_OBQ_PI_ADDR, LE_64(softs->admin_ob_queue.pi_dma_addr)); | ||||
Context not available. | |||||
admin_q_param = softs->admin_ib_queue.num_elem | | admin_q_param = softs->admin_ib_queue.num_elem | | ||||
(softs->admin_ob_queue.num_elem << 8)| | (softs->admin_ob_queue.num_elem << 8)| | ||||
PQI_ADMIN_QUEUE_MSIX_DISABLE; | PQI_ADMIN_QUEUE_MSIX_DISABLE; | ||||
PCI_MEM_PUT32(softs, &softs->pqi_reg->admin_q_param, | PCI_MEM_PUT32(softs, &softs->pqi_reg->admin_q_param, | ||||
PQI_ADMINQ_PARAM, LE_32(admin_q_param)); | PQI_ADMINQ_PARAM, LE_32(admin_q_param)); | ||||
/* Submit cmd to create Admin Q pair */ | /* Submit cmd to create Admin Q pair */ | ||||
ret = pqisrc_create_delete_adminq(softs, | ret = pqisrc_create_delete_adminq(softs, | ||||
PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR); | PQI_ADMIN_QUEUE_CONF_FUNC_CREATE_Q_PAIR); | ||||
Context not available. | |||||
DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret); | DBG_ERR("Failed to Allocate Admin Q ret : %d\n", ret); | ||||
goto err_q_create; | goto err_q_create; | ||||
} | } | ||||
/* Admin queue created, get ci,pi offset */ | /* Admin queue created, get ci,pi offset */ | ||||
softs->admin_ib_queue.pi_register_offset =(PQISRC_PQI_REG_OFFSET + | softs->admin_ib_queue.pi_register_offset =(PQISRC_PQI_REG_OFFSET + | ||||
PCI_MEM_GET64(softs, &softs->pqi_reg->admin_ibq_pi_offset, PQI_ADMIN_IBQ_PI_OFFSET)); | PCI_MEM_GET64(softs, &softs->pqi_reg->admin_ibq_pi_offset, PQI_ADMIN_IBQ_PI_OFFSET)); | ||||
softs->admin_ib_queue.pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + | softs->admin_ib_queue.pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + | ||||
softs->admin_ib_queue.pi_register_offset); | softs->admin_ib_queue.pi_register_offset); | ||||
softs->admin_ob_queue.ci_register_offset = (PQISRC_PQI_REG_OFFSET + | softs->admin_ob_queue.ci_register_offset = (PQISRC_PQI_REG_OFFSET + | ||||
PCI_MEM_GET64(softs, &softs->pqi_reg->admin_obq_ci_offset, PQI_ADMIN_OBQ_CI_OFFSET)); | PCI_MEM_GET64(softs, &softs->pqi_reg->admin_obq_ci_offset, PQI_ADMIN_OBQ_CI_OFFSET)); | ||||
softs->admin_ob_queue.ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + | softs->admin_ob_queue.ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + | ||||
softs->admin_ob_queue.ci_register_offset); | softs->admin_ob_queue.ci_register_offset); | ||||
os_strlcpy(softs->admin_ib_queue.lockname, "admin_ibqlock", LOCKNAME_SIZE); | os_strlcpy(softs->admin_ib_queue.lockname, "admin_ibqlock", LOCKNAME_SIZE); | ||||
ret =OS_INIT_PQILOCK(softs, &softs->admin_ib_queue.lock, | ret =OS_INIT_PQILOCK(softs, &softs->admin_ib_queue.lock, | ||||
softs->admin_ib_queue.lockname); | softs->admin_ib_queue.lockname); | ||||
if(ret){ | if(ret){ | ||||
Context not available. | |||||
/* Print admin q config details */ | /* Print admin q config details */ | ||||
pqisrc_print_adminq_config(softs); | pqisrc_print_adminq_config(softs); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
Context not available. | |||||
admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_IQ; | admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_IQ; | ||||
else | else | ||||
admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_OQ; | admin_req.fn_code = PQI_FUNCTION_DELETE_OPERATIONAL_OQ; | ||||
ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
#endif | #endif | ||||
return ret; | return ret; | ||||
Context not available. | |||||
} | } | ||||
softs->event_q.created = false; | softs->event_q.created = false; | ||||
} | } | ||||
/* Free the memory */ | /* Free the memory */ | ||||
os_dma_mem_free(softs, &softs->event_q_dma_mem); | os_dma_mem_free(softs, &softs->event_q_dma_mem); | ||||
Context not available. | |||||
ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, true); | ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, true); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Delete Raid IB Q %d\n",op_ib_q->q_id); | DBG_ERR("Failed to Delete Raid IB Q %d\n",op_ib_q->q_id); | ||||
} | } | ||||
op_ib_q->created = false; | op_ib_q->created = false; | ||||
} | } | ||||
if(op_ib_q->lockcreated==true){ | if(op_ib_q->lockcreated==true){ | ||||
OS_UNINIT_PQILOCK(&op_ib_q->lock); | OS_UNINIT_PQILOCK(&op_ib_q->lock); | ||||
op_ib_q->lockcreated = false; | op_ib_q->lockcreated = false; | ||||
} | } | ||||
/* OP AIO IB Q */ | /* OP AIO IB Q */ | ||||
op_ib_q = &softs->op_aio_ib_q[i]; | op_ib_q = &softs->op_aio_ib_q[i]; | ||||
if (op_ib_q->created == true) { | if (op_ib_q->created == true) { | ||||
Context not available. | |||||
} | } | ||||
op_ib_q->created = false; | op_ib_q->created = false; | ||||
} | } | ||||
if(op_ib_q->lockcreated==true){ | if(op_ib_q->lockcreated==true){ | ||||
OS_UNINIT_PQILOCK(&op_ib_q->lock); | OS_UNINIT_PQILOCK(&op_ib_q->lock); | ||||
op_ib_q->lockcreated = false; | op_ib_q->lockcreated = false; | ||||
Context not available. | |||||
#if 0 | #if 0 | ||||
ret = pqisrc_create_delete_adminq(softs, | ret = pqisrc_create_delete_adminq(softs, | ||||
PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR); | PQI_ADMIN_QUEUE_CONF_FUNC_DEL_Q_PAIR); | ||||
#endif | #endif | ||||
os_dma_mem_free(softs, &softs->admin_queue_dma_mem); | os_dma_mem_free(softs, &softs->admin_queue_dma_mem); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
} | } | ||||
Context not available. | |||||
memset(&admin_req, 0, sizeof(admin_req)); | memset(&admin_req, 0, sizeof(admin_req)); | ||||
memset(&admin_resp, 0, sizeof(admin_resp)); | memset(&admin_resp, 0, sizeof(admin_resp)); | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
admin_req.fn_code = PQI_FUNCTION_CHANGE_OPERATIONAL_IQ_PROP; | admin_req.fn_code = PQI_FUNCTION_CHANGE_OPERATIONAL_IQ_PROP; | ||||
admin_req.req_type.change_op_iq_prop.qid = op_ib_q->q_id; | admin_req.req_type.change_op_iq_prop.qid = op_ib_q->q_id; | ||||
admin_req.req_type.change_op_iq_prop.vend_specific = prop; | admin_req.req_type.change_op_iq_prop.vend_specific = prop; | ||||
ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
} | } | ||||
Context not available. | |||||
memset(&admin_resp, 0, sizeof(admin_resp)); | memset(&admin_resp, 0, sizeof(admin_resp)); | ||||
admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_OQ; | admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_OQ; | ||||
admin_req.req_type.create_op_oq.qid = op_ob_q->q_id; | admin_req.req_type.create_op_oq.qid = op_ob_q->q_id; | ||||
admin_req.req_type.create_op_oq.intr_msg_num = op_ob_q->intr_msg_num; | admin_req.req_type.create_op_oq.intr_msg_num = op_ob_q->intr_msg_num; | ||||
admin_req.req_type.create_op_oq.elem_arr_addr = op_ob_q->array_dma_addr; | admin_req.req_type.create_op_oq.elem_arr_addr = op_ob_q->array_dma_addr; | ||||
admin_req.req_type.create_op_oq.ob_pi_addr = op_ob_q->pi_dma_addr; | admin_req.req_type.create_op_oq.ob_pi_addr = op_ob_q->pi_dma_addr; | ||||
Context not available. | |||||
ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ||||
if( PQI_STATUS_SUCCESS == ret) { | if( PQI_STATUS_SUCCESS == ret) { | ||||
op_ob_q->ci_register_offset = (PQISRC_PQI_REG_OFFSET + | op_ob_q->ci_register_offset = (PQISRC_PQI_REG_OFFSET + | ||||
admin_resp.resp_type.create_op_oq.ci_offset); | admin_resp.resp_type.create_op_oq.ci_offset); | ||||
op_ob_q->ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + | op_ob_q->ci_register_abs = (uint32_t *)(softs->pci_mem_base_vaddr + | ||||
op_ob_q->ci_register_offset); | op_ob_q->ci_register_offset); | ||||
Context not available. | |||||
int i = 0; | int i = 0; | ||||
DBG_WARN("Error Status Descriptors\n"); | DBG_WARN("Error Status Descriptors\n"); | ||||
for(i = 0; i < 4;i++) | for(i = 0; i < 4;i++) | ||||
DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]); | DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]); | ||||
} | } | ||||
DBG_FUNC("OUT ret : %d\n", ret); | DBG_FUNC("OUT ret : %d\n", ret); | ||||
Context not available. | |||||
admin_req.req_type.create_op_iq.iq_ci_addr = op_ib_q->ci_dma_addr; | admin_req.req_type.create_op_iq.iq_ci_addr = op_ib_q->ci_dma_addr; | ||||
admin_req.req_type.create_op_iq.num_elem = op_ib_q->num_elem; | admin_req.req_type.create_op_iq.num_elem = op_ib_q->num_elem; | ||||
admin_req.req_type.create_op_iq.elem_len = op_ib_q->elem_size / 16; | admin_req.req_type.create_op_iq.elem_len = op_ib_q->elem_size / 16; | ||||
ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp); | ||||
if( PQI_STATUS_SUCCESS == ret) { | if( PQI_STATUS_SUCCESS == ret) { | ||||
op_ib_q->pi_register_offset =(PQISRC_PQI_REG_OFFSET + | op_ib_q->pi_register_offset =(PQISRC_PQI_REG_OFFSET + | ||||
admin_resp.resp_type.create_op_iq.pi_offset); | admin_resp.resp_type.create_op_iq.pi_offset); | ||||
op_ib_q->pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + | op_ib_q->pi_register_abs =(uint32_t *)(softs->pci_mem_base_vaddr + | ||||
op_ib_q->pi_register_offset); | op_ib_q->pi_register_offset); | ||||
} else { | } else { | ||||
int i = 0; | int i = 0; | ||||
DBG_WARN("Error Status Decsriptors\n"); | DBG_WARN("Error Status Decsriptors\n"); | ||||
for(i = 0; i < 4;i++) | for(i = 0; i < 4;i++) | ||||
DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]); | DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]); | ||||
} | } | ||||
DBG_FUNC("OUT ret : %d\n", ret); | DBG_FUNC("OUT ret : %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
ret = pqisrc_create_op_ibq(softs,op_aio_ib_q); | ret = pqisrc_create_op_ibq(softs,op_aio_ib_q); | ||||
if ( PQI_STATUS_SUCCESS == ret) | if ( PQI_STATUS_SUCCESS == ret) | ||||
ret = pqisrc_change_op_ibq_queue_prop(softs, | ret = pqisrc_change_op_ibq_queue_prop(softs, | ||||
Context not available. | |||||
ib_queue_t *op_raid_ib_q) | ib_queue_t *op_raid_ib_q) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
ret = pqisrc_create_op_ibq(softs,op_raid_ib_q); | ret = pqisrc_create_op_ibq(softs,op_raid_ib_q); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
} | } | ||||
Context not available. | |||||
uint32_t num_elem; | uint32_t num_elem; | ||||
char *virt_addr = NULL; | char *virt_addr = NULL; | ||||
dma_addr_t dma_addr = 0; | dma_addr_t dma_addr = 0; | ||||
uint32_t event_q_pi_dma_start_offset = 0; | uint64_t event_q_pi_dma_start_offset = 0; | ||||
uint32_t event_q_pi_virt_start_offset = 0; | uint32_t event_q_pi_virt_start_offset = 0; | ||||
char *event_q_pi_virt_start_addr = NULL; | char *event_q_pi_virt_start_addr = NULL; | ||||
ob_queue_t *event_q = NULL; | ob_queue_t *event_q = NULL; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
/* | /* | ||||
* Calculate memory requirements. | * Calculate memory requirements. | ||||
* If event queue is shared for IO response, number of | * If event queue is shared for IO response, number of | ||||
* elements in event queue depends on num elements in OP OB Q | * elements in event queue depends on num elements in OP OB Q | ||||
* also. Since event queue element size (32) is more than IO | * also. Since event queue element size (32) is more than IO | ||||
* response size , event queue element size need not be checked | * response size , event queue element size need not be checked | ||||
* for queue size calculation. | * for queue size calculation. | ||||
*/ | */ | ||||
#ifdef SHARE_EVENT_QUEUE_FOR_IO | #ifdef SHARE_EVENT_QUEUE_FOR_IO | ||||
num_elem = MIN(softs->num_elem_per_op_obq, PQISRC_NUM_EVENT_Q_ELEM); | num_elem = MIN(softs->num_elem_per_op_obq, PQISRC_NUM_EVENT_Q_ELEM); | ||||
#else | #else | ||||
num_elem = PQISRC_NUM_EVENT_Q_ELEM; | num_elem = PQISRC_NUM_EVENT_Q_ELEM; | ||||
Context not available. | |||||
dma_addr = softs->event_q_dma_mem.dma_addr; | dma_addr = softs->event_q_dma_mem.dma_addr; | ||||
event_q_pi_dma_start_offset += dma_addr; | event_q_pi_dma_start_offset += dma_addr; | ||||
event_q_pi_virt_start_addr = virt_addr + event_q_pi_virt_start_offset; | event_q_pi_virt_start_addr = virt_addr + event_q_pi_virt_start_offset; | ||||
event_q = &softs->event_q; | event_q = &softs->event_q; | ||||
ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); | ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); | ||||
FILL_QUEUE_ARRAY_ADDR(event_q,virt_addr,dma_addr); | FILL_QUEUE_ARRAY_ADDR(event_q,virt_addr,dma_addr); | ||||
Context not available. | |||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_out_create: | err_out_create: | ||||
pqisrc_destroy_event_queue(softs); | pqisrc_destroy_event_queue(softs); | ||||
err_out: | err_out: | ||||
Context not available. | |||||
/* | /* | ||||
* Allocate DMA memory and create operational ib queues. | * Allocate DMA memory and create operational ib queues. | ||||
*/ | */ | ||||
int pqisrc_alloc_and_create_ib_queues(pqisrc_softstate_t *softs) | int pqisrc_alloc_and_create_ib_queues(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
Context not available. | |||||
char *virt_addr = NULL; | char *virt_addr = NULL; | ||||
dma_addr_t dma_addr = 0; | dma_addr_t dma_addr = 0; | ||||
uint32_t ibq_size = 0; | uint32_t ibq_size = 0; | ||||
uint32_t ib_ci_dma_start_offset = 0; | uint64_t ib_ci_dma_start_offset = 0; | ||||
char *ib_ci_virt_start_addr = NULL; | char *ib_ci_virt_start_addr = NULL; | ||||
uint32_t ib_ci_virt_start_offset = 0; | uint32_t ib_ci_virt_start_offset = 0; | ||||
uint32_t ibq_id = PQI_MIN_OP_IB_QUEUE_ID; | uint32_t ibq_id = PQI_MIN_OP_IB_QUEUE_ID; | ||||
ib_queue_t *op_ib_q = NULL; | ib_queue_t *op_ib_q = NULL; | ||||
uint32_t num_op_ibq = softs->num_op_raid_ibq + | uint32_t num_op_ibq = softs->num_op_raid_ibq + | ||||
softs->num_op_aio_ibq; | softs->num_op_aio_ibq; | ||||
int i = 0; | int i = 0; | ||||
Context not available. | |||||
/* Calculate memory requirements */ | /* Calculate memory requirements */ | ||||
ibq_size = softs->num_elem_per_op_ibq * softs->ibq_elem_size; | ibq_size = softs->num_elem_per_op_ibq * softs->ibq_elem_size; | ||||
alloc_size = num_op_ibq * ibq_size; | alloc_size = num_op_ibq * ibq_size; | ||||
/* CI indexes starts after Queue element array */ | /* CI indexes starts after Queue element array */ | ||||
ib_ci_dma_start_offset = alloc_size; | ib_ci_dma_start_offset = alloc_size; | ||||
ib_ci_virt_start_offset = alloc_size; | ib_ci_virt_start_offset = alloc_size; | ||||
alloc_size += num_op_ibq * sizeof(uint32_t); /*For IBQ CI*/ | alloc_size += num_op_ibq * sizeof(uint32_t); /*For IBQ CI*/ | ||||
Context not available. | |||||
ib_ci_virt_start_addr = virt_addr + ib_ci_virt_start_offset; | ib_ci_virt_start_addr = virt_addr + ib_ci_virt_start_offset; | ||||
ASSERT(softs->num_op_raid_ibq == softs->num_op_aio_ibq); | ASSERT(softs->num_op_raid_ibq == softs->num_op_aio_ibq); | ||||
for (i = 0; i < softs->num_op_raid_ibq; i++) { | for (i = 0; i < softs->num_op_raid_ibq; i++) { | ||||
/* OP RAID IB Q */ | /* OP RAID IB Q */ | ||||
op_ib_q = &softs->op_raid_ib_q[i]; | op_ib_q = &softs->op_raid_ib_q[i]; | ||||
Context not available. | |||||
FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr); | FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr); | ||||
op_ib_q->q_id = ibq_id++; | op_ib_q->q_id = ibq_id++; | ||||
snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "raid_ibqlock%d", i); | snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "raid_ibqlock%d", i); | ||||
ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); | ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); | ||||
if(ret){ | if(ret){ | ||||
DBG_ERR("raid_ibqlock %d init failed\n", i); | /* TODO: error handling */ | ||||
op_ib_q->lockcreated = false; | DBG_ERR("raid_ibqlock %d init failed\n", i); | ||||
goto err_lock; | op_ib_q->lockcreated = false; | ||||
goto err_lock; | |||||
} | } | ||||
op_ib_q->lockcreated = true; | op_ib_q->lockcreated = true; | ||||
op_ib_q->num_elem = softs->num_elem_per_op_ibq; | |||||
op_ib_q->num_elem = softs->num_elem_per_op_ibq; | |||||
op_ib_q->elem_size = softs->ibq_elem_size; | op_ib_q->elem_size = softs->ibq_elem_size; | ||||
op_ib_q->ci_dma_addr = ib_ci_dma_start_offset + | op_ib_q->ci_dma_addr = ib_ci_dma_start_offset + | ||||
(2 * i * sizeof(uint32_t)); | (2 * i * sizeof(uint32_t)); | ||||
op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr + | op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr + | ||||
(2 * i * sizeof(uint32_t))); | (2 * i * sizeof(uint32_t))); | ||||
ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ||||
ret = pqisrc_create_op_raid_ibq(softs, op_ib_q); | ret = pqisrc_create_op_raid_ibq(softs, op_ib_q); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("[ %s ] Failed to Create OP Raid IBQ %d\n", | DBG_ERR("[ %s ] Failed to Create OP Raid IBQ %d\n", | ||||
Context not available. | |||||
ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); | ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); | ||||
FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr); | FILL_QUEUE_ARRAY_ADDR(op_ib_q,virt_addr,dma_addr); | ||||
op_ib_q->q_id = ibq_id++; | op_ib_q->q_id = ibq_id++; | ||||
snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "aio_ibqlock%d", i); | snprintf(op_ib_q->lockname, LOCKNAME_SIZE, "aio_ibqlock%d", i); | ||||
ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); | ret = OS_INIT_PQILOCK(softs, &op_ib_q->lock, op_ib_q->lockname); | ||||
if(ret){ | if(ret){ | ||||
DBG_ERR("aio_ibqlock %d init failed\n", i); | /* TODO: error handling */ | ||||
op_ib_q->lockcreated = false; | DBG_ERR("aio_ibqlock %d init failed\n", i); | ||||
goto err_lock; | op_ib_q->lockcreated = false; | ||||
} | goto err_lock; | ||||
op_ib_q->lockcreated = true; | } | ||||
op_ib_q->num_elem = softs->num_elem_per_op_ibq; | op_ib_q->lockcreated = true; | ||||
op_ib_q->num_elem = softs->num_elem_per_op_ibq; | |||||
op_ib_q->elem_size = softs->ibq_elem_size; | op_ib_q->elem_size = softs->ibq_elem_size; | ||||
op_ib_q->ci_dma_addr = ib_ci_dma_start_offset + | op_ib_q->ci_dma_addr = ib_ci_dma_start_offset + | ||||
(((2 * i) + 1) * sizeof(uint32_t)); | (((2 * i) + 1) * sizeof(uint32_t)); | ||||
op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr + | op_ib_q->ci_virt_addr = (uint32_t*)(ib_ci_virt_start_addr + | ||||
(((2 * i) + 1) * sizeof(uint32_t))); | (((2 * i) + 1) * sizeof(uint32_t))); | ||||
ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ASSERT(!(op_ib_q->ci_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ||||
ret = pqisrc_create_op_aio_ibq(softs, op_ib_q); | ret = pqisrc_create_op_aio_ibq(softs, op_ib_q); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Create OP AIO IBQ %d\n",op_ib_q->q_id); | DBG_ERR("Failed to Create OP AIO IBQ %d\n",op_ib_q->q_id); | ||||
goto err_out_create; | goto err_out_create; | ||||
} | } | ||||
op_ib_q->created = true; | op_ib_q->created = true; | ||||
virt_addr += ibq_size; | virt_addr += ibq_size; | ||||
dma_addr += ibq_size; | dma_addr += ibq_size; | ||||
} | } | ||||
Context not available. | |||||
/* | /* | ||||
* Allocate DMA memory and create operational ob queues. | * Allocate DMA memory and create operational ob queues. | ||||
*/ | */ | ||||
int pqisrc_alloc_and_create_ob_queues(pqisrc_softstate_t *softs) | int pqisrc_alloc_and_create_ob_queues(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
Context not available. | |||||
char *virt_addr = NULL; | char *virt_addr = NULL; | ||||
dma_addr_t dma_addr = 0; | dma_addr_t dma_addr = 0; | ||||
uint32_t obq_size = 0; | uint32_t obq_size = 0; | ||||
uint32_t ob_pi_dma_start_offset = 0; | uint64_t ob_pi_dma_start_offset = 0; | ||||
uint32_t ob_pi_virt_start_offset = 0; | uint32_t ob_pi_virt_start_offset = 0; | ||||
char *ob_pi_virt_start_addr = NULL; | char *ob_pi_virt_start_addr = NULL; | ||||
uint32_t obq_id = PQI_MIN_OP_OB_QUEUE_ID; | uint32_t obq_id = PQI_MIN_OP_OB_QUEUE_ID; | ||||
Context not available. | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
/* | /* | ||||
* OB Q element array should be 64 byte aligned. | * OB Q element array should be 64 byte aligned. | ||||
* So the number of elements in OB Q should be multiple | * So the number of elements in OB Q should be multiple | ||||
* of 4, so that OB Queue element size (16) * num elements | * of 4, so that OB Queue element size (16) * num elements | ||||
* will be multiple of 64. | * will be multiple of 64. | ||||
*/ | */ | ||||
ALIGN_BOUNDARY(softs->num_elem_per_op_obq, 4); | ALIGN_BOUNDARY(softs->num_elem_per_op_obq, 4); | ||||
obq_size = softs->num_elem_per_op_obq * softs->obq_elem_size; | obq_size = softs->num_elem_per_op_obq * softs->obq_elem_size; | ||||
alloc_size += num_op_obq * obq_size; | alloc_size += num_op_obq * obq_size; | ||||
/* PI indexes starts after Queue element array */ | /* PI indexes starts after Queue element array */ | ||||
ob_pi_dma_start_offset = alloc_size; | ob_pi_dma_start_offset = alloc_size; | ||||
ob_pi_virt_start_offset = alloc_size; | ob_pi_virt_start_offset = alloc_size; | ||||
alloc_size += num_op_obq * sizeof(uint32_t); /*For OBQ PI*/ | alloc_size += num_op_obq * sizeof(uint32_t); /*For OBQ PI*/ | ||||
Context not available. | |||||
DBG_INFO("softs->num_op_obq %d\n",softs->num_op_obq); | DBG_INFO("softs->num_op_obq %d\n",softs->num_op_obq); | ||||
for (i = 0; i < softs->num_op_obq; i++) { | for (i = 0; i < softs->num_op_obq; i++) { | ||||
op_ob_q = &softs->op_ob_q[i]; | op_ob_q = &softs->op_ob_q[i]; | ||||
ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); | ASSERT(!(dma_addr & PQI_ADDR_ALIGN_MASK_64)); | ||||
FILL_QUEUE_ARRAY_ADDR(op_ob_q,virt_addr,dma_addr); | FILL_QUEUE_ARRAY_ADDR(op_ob_q,virt_addr,dma_addr); | ||||
op_ob_q->q_id = obq_id++; | op_ob_q->q_id = obq_id++; | ||||
if(softs->share_opq_and_eventq == true) | if(softs->share_opq_and_eventq == true) | ||||
op_ob_q->intr_msg_num = i; | op_ob_q->intr_msg_num = i; | ||||
else | else | ||||
op_ob_q->intr_msg_num = i + 1; /* msg num zero for event */ | op_ob_q->intr_msg_num = i + 1; /* msg num zero for event */ | ||||
op_ob_q->num_elem = softs->num_elem_per_op_obq; | op_ob_q->num_elem = softs->num_elem_per_op_obq; | ||||
op_ob_q->elem_size = softs->obq_elem_size; | op_ob_q->elem_size = softs->obq_elem_size; | ||||
op_ob_q->pi_dma_addr = ob_pi_dma_start_offset + | op_ob_q->pi_dma_addr = ob_pi_dma_start_offset + | ||||
Context not available. | |||||
op_ob_q->pi_virt_addr = (uint32_t*)(ob_pi_virt_start_addr + | op_ob_q->pi_virt_addr = (uint32_t*)(ob_pi_virt_start_addr + | ||||
(i * sizeof(uint32_t))); | (i * sizeof(uint32_t))); | ||||
ASSERT(!(op_ob_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ASSERT(!(op_ob_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ||||
ret = pqisrc_create_op_obq(softs,op_ob_q); | ret = pqisrc_create_op_obq(softs,op_ob_q); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Create OP OBQ %d\n",op_ob_q->q_id); | DBG_ERR("Failed to Create OP OBQ %d\n",op_ob_q->q_id); | ||||
Context not available. | |||||
virt_addr += obq_size; | virt_addr += obq_size; | ||||
dma_addr += obq_size; | dma_addr += obq_size; | ||||
} | } | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_out_create: | err_out_create: | ||||
pqisrc_destroy_op_ob_queues(softs); | pqisrc_destroy_op_ob_queues(softs); | ||||
err_out: | err_out: | ||||
Context not available. | |||||
/* | /* | ||||
* Function used to create operational queues for the adapter. | * Function used to create operational queues for the adapter. | ||||
*/ | */ | ||||
int pqisrc_create_op_queues(pqisrc_softstate_t *softs) | int pqisrc_create_op_queues(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
/* Create Operational IB queues */ | /* Create Operational IB queues */ | ||||
ret = pqisrc_alloc_and_create_ib_queues(softs); | ret = pqisrc_alloc_and_create_ib_queues(softs); | ||||
if (ret) | if (ret) | ||||
Context not available. | |||||
/* Create Event queue */ | /* Create Event queue */ | ||||
ret = pqisrc_alloc_and_create_event_queue(softs); | ret = pqisrc_alloc_and_create_event_queue(softs); | ||||
if (ret) | if (ret) | ||||
goto err_out_eventq; | goto err_out_eventq; | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_out_eventq: | err_out_eventq: | ||||
pqisrc_destroy_op_ob_queues(softs); | pqisrc_destroy_op_ob_queues(softs); | ||||
err_out_obq: | err_out_obq: | ||||
pqisrc_destroy_op_ib_queues(softs); | pqisrc_destroy_op_ib_queues(softs); | ||||
err_out: | err_out: | ||||
Context not available. |