Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/smartpqi/smartpqi_queue.c
/*- | /*- | ||||
* Copyright (c) 2018 Microsemi Corporation. | * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries. | ||||
* 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 | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
* notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the | ||||
Show All 15 Lines | |||||
/* $FreeBSD$ */ | /* $FreeBSD$ */ | ||||
#include "smartpqi_includes.h" | #include "smartpqi_includes.h" | ||||
/* | /* | ||||
* Submit an admin IU to the adapter. | * Submit an admin IU to the adapter. | ||||
* Add interrupt support, if required | * Add interrupt support, if required | ||||
*/ | */ | ||||
int pqisrc_submit_admin_req(pqisrc_softstate_t *softs, | int | ||||
pqisrc_submit_admin_req(pqisrc_softstate_t *softs, | |||||
gen_adm_req_iu_t *req, gen_adm_resp_iu_t *resp) | gen_adm_req_iu_t *req, gen_adm_resp_iu_t *resp) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
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 = | ||||
PQI_IU_TYPE_GENERAL_ADMIN_REQUEST; | PQI_IU_TYPE_GENERAL_ADMIN_REQUEST; | ||||
req->header.comp_feature = 0x00; | req->header.comp_feature = 0x00; | ||||
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) { | ||||
DBG_ERR("Tag not available0x%x\n",(uint16_t)req->req_id); | DBG_ERR("Tag not available0x%x\n",(uint16_t)req->req_id); | ||||
ret = PQI_STATUS_FAILURE; | ret = PQI_STATUS_FAILURE; | ||||
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) { | ||||
DBG_ERR("Unable to submit command\n"); | DBG_ERR("Unable to submit command\n"); | ||||
goto err_cmd; | goto err_cmd; | ||||
} | } | ||||
/* Wait for completion */ | /* Wait for completion */ | ||||
COND_WAIT((*(ob_q->pi_virt_addr) != ob_q->ci_local), tmo); | COND_WAIT((*(ob_q->pi_virt_addr) != ob_q->ci_local), tmo); | ||||
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); | ||||
ret = resp->status; | ret = resp->status; | ||||
if (ret) | if (ret) | ||||
goto err_cmd; | goto err_cmd; | ||||
os_reset_rcb(&softs->rcb[req->req_id]); | os_reset_rcb(&softs->rcb[req->req_id]); | ||||
pqisrc_put_tag(&softs->taglist,req->req_id); | pqisrc_put_tag(&softs->taglist,req->req_id); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_cmd: | err_cmd: | ||||
os_reset_rcb(&softs->rcb[req->req_id]); | os_reset_rcb(&softs->rcb[req->req_id]); | ||||
pqisrc_put_tag(&softs->taglist,req->req_id); | pqisrc_put_tag(&softs->taglist,req->req_id); | ||||
err_out: | err_out: | ||||
DBG_FUNC("failed OUT : %d\n", ret); | DBG_FUNC("failed OUT : %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* Get the administration queue config parameters. | * Get the administration queue config parameters. | ||||
*/ | */ | ||||
void pqisrc_get_admin_queue_config(pqisrc_softstate_t *softs) | void | ||||
pqisrc_get_admin_queue_config(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
uint64_t val = 0; | uint64_t val = 0; | ||||
val = LE_64(PCI_MEM_GET64(softs, &softs->pqi_reg->pqi_dev_adminq_cap, PQI_ADMINQ_CAP)); | val = LE_64(PCI_MEM_GET64(softs, &softs->pqi_reg->pqi_dev_adminq_cap, PQI_ADMINQ_CAP)); | ||||
/* pqi_cap = (struct pqi_dev_adminq_cap *)&val;*/ | /* pqi_cap = (struct pqi_dev_adminq_cap *)&val;*/ | ||||
softs->admin_ib_queue.num_elem = val & 0xFF; | softs->admin_ib_queue.num_elem = val & 0xFF; | ||||
softs->admin_ob_queue.num_elem = (val & 0xFF00) >> 8; | softs->admin_ob_queue.num_elem = (val & 0xFF00) >> 8; | ||||
/* 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", | ||||
softs->admin_ib_queue.elem_size); | softs->admin_ib_queue.elem_size); | ||||
} | } | ||||
/* | /* | ||||
* 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); | ||||
} | } | ||||
/* | /* | ||||
* Allocate DMA memory for admin queue and initialize. | * Allocate DMA memory for admin queue and initialize. | ||||
*/ | */ | ||||
int pqisrc_allocate_and_init_adminq(pqisrc_softstate_t *softs) | int | ||||
pqisrc_allocate_and_init_adminq(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
uint32_t ib_array_size = 0; | uint32_t ib_array_size = 0; | ||||
uint32_t ob_array_size = 0; | uint32_t ob_array_size = 0; | ||||
uint32_t alloc_size = 0; | uint32_t alloc_size = 0; | ||||
char *virt_addr = NULL; | char *virt_addr = NULL; | ||||
dma_addr_t dma_addr = 0; | dma_addr_t dma_addr = 0; | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
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); | ||||
alloc_size = ib_array_size + ob_array_size + | alloc_size = ib_array_size + ob_array_size + | ||||
2 * sizeof(uint32_t) + PQI_ADDR_ALIGN_MASK_64 + 1; /* for IB CI and OB PI */ | 2 * sizeof(uint32_t) + PQI_ADDR_ALIGN_MASK_64 + 1; /* for IB CI and OB PI */ | ||||
/* Allocate memory for Admin Q */ | /* Allocate memory for Admin Q */ | ||||
softs->admin_queue_dma_mem.tag = "admin_queue"; | softs->admin_queue_dma_mem.tag = "admin_queue"; | ||||
softs->admin_queue_dma_mem.size = alloc_size; | softs->admin_queue_dma_mem.size = alloc_size; | ||||
Show All 13 Lines | pqisrc_allocate_and_init_adminq(pqisrc_softstate_t *softs) | ||||
softs->admin_ib_queue.array_virt_addr = virt_addr; | softs->admin_ib_queue.array_virt_addr = virt_addr; | ||||
softs->admin_ib_queue.array_dma_addr = dma_addr; | softs->admin_ib_queue.array_dma_addr = dma_addr; | ||||
softs->admin_ib_queue.pi_local = 0; | softs->admin_ib_queue.pi_local = 0; | ||||
/* OB */ | /* OB */ | ||||
softs->admin_ob_queue.q_id = 0; | softs->admin_ob_queue.q_id = 0; | ||||
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", | ||||
(void*)softs->admin_ib_queue.ci_dma_addr, (void*)softs->admin_ob_queue.pi_dma_addr ); | (void*)softs->admin_ib_queue.ci_dma_addr, (void*)softs->admin_ob_queue.pi_dma_addr ); | ||||
/* Verify alignment */ | /* Verify alignment */ | ||||
ASSERT(!(softs->admin_ib_queue.array_dma_addr & | ASSERT(!(softs->admin_ib_queue.array_dma_addr & | ||||
PQI_ADDR_ALIGN_MASK_64)); | PQI_ADDR_ALIGN_MASK_64)); | ||||
Show All 10 Lines | |||||
err_out: | err_out: | ||||
DBG_FUNC("failed OUT\n"); | DBG_FUNC("failed OUT\n"); | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
} | } | ||||
/* | /* | ||||
* Subroutine used to create (or) delete the admin queue requested. | * Subroutine used to create (or) delete the admin queue requested. | ||||
*/ | */ | ||||
int pqisrc_create_delete_adminq(pqisrc_softstate_t *softs, | int | ||||
uint32_t cmd) | pqisrc_create_delete_adminq(pqisrc_softstate_t *softs, uint32_t cmd) | ||||
{ | { | ||||
int tmo = 0; | int tmo = 0; | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
/* 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. | ||||
*/ | */ | ||||
void pqisrc_print_adminq_config(pqisrc_softstate_t *softs) | void | ||||
pqisrc_print_adminq_config(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
DBG_INFO(" softs->admin_ib_queue.array_dma_addr : %p\n", | DBG_INFO(" softs->admin_ib_queue.array_dma_addr : %p\n", | ||||
(void*)softs->admin_ib_queue.array_dma_addr); | (void*)softs->admin_ib_queue.array_dma_addr); | ||||
DBG_INFO(" softs->admin_ib_queue.array_virt_addr : %p\n", | DBG_INFO(" softs->admin_ib_queue.array_virt_addr : %p\n", | ||||
(void*)softs->admin_ib_queue.array_virt_addr); | (void*)softs->admin_ib_queue.array_virt_addr); | ||||
DBG_INFO(" softs->admin_ib_queue.num_elem : %d\n", | DBG_INFO(" softs->admin_ib_queue.num_elem : %d\n", | ||||
softs->admin_ib_queue.num_elem); | softs->admin_ib_queue.num_elem); | ||||
DBG_INFO(" softs->admin_ib_queue.elem_size : %d\n", | DBG_INFO(" softs->admin_ib_queue.elem_size : %d\n", | ||||
Show All 10 Lines | DBG_INFO(" softs->admin_ib_queue.pi_register_abs : %p\n", | ||||
(void*)softs->admin_ib_queue.pi_register_abs); | (void*)softs->admin_ib_queue.pi_register_abs); | ||||
DBG_INFO(" softs->admin_ob_queue.ci_register_abs : %p\n", | DBG_INFO(" softs->admin_ob_queue.ci_register_abs : %p\n", | ||||
(void*)softs->admin_ob_queue.ci_register_abs); | (void*)softs->admin_ob_queue.ci_register_abs); | ||||
} | } | ||||
/* | /* | ||||
* Function used to create an admin queue. | * Function used to create an admin queue. | ||||
*/ | */ | ||||
int pqisrc_create_admin_queue(pqisrc_softstate_t *softs) | int | ||||
pqisrc_create_admin_queue(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS;; | int ret = PQI_STATUS_SUCCESS; | ||||
uint32_t admin_q_param = 0; | uint32_t admin_q_param = 0; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
/* Get admin queue details - pqi2-r00a - table 24 */ | /* Get admin queue details - pqi2-r00a - table 24 */ | ||||
pqisrc_get_admin_queue_config(softs); | pqisrc_get_admin_queue_config(softs); | ||||
/* Decide admin Q config */ | /* Decide admin Q config */ | ||||
pqisrc_decide_admin_queue_config(softs); | pqisrc_decide_admin_queue_config(softs); | ||||
/* Allocate and init Admin Q pair */ | /* Allocate and init Admin Q pair */ | ||||
ret = pqisrc_allocate_and_init_adminq(softs); | ret = pqisrc_allocate_and_init_adminq(softs); | ||||
if (ret) { | if (ret) { | ||||
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)); | ||||
/* Write Admin Q params pqi-r200a table 36 */ | /* Write Admin Q params pqi-r200a table 36 */ | ||||
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); | ||||
if (ret) { | if (ret) { | ||||
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){ | ||||
DBG_ERR("Admin spinlock initialization failed\n"); | DBG_ERR("Admin spinlock initialization failed\n"); | ||||
softs->admin_ib_queue.lockcreated = false; | softs->admin_ib_queue.lockcreated = false; | ||||
goto err_lock; | goto err_lock; | ||||
} | } | ||||
softs->admin_ib_queue.lockcreated = true; | softs->admin_ib_queue.lockcreated = true; | ||||
/* 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; | ||||
err_lock: | err_lock: | ||||
err_q_create: | err_q_create: | ||||
os_dma_mem_free(softs, &softs->admin_queue_dma_mem); | os_dma_mem_free(softs, &softs->admin_queue_dma_mem); | ||||
err_out: | err_out: | ||||
DBG_FUNC("failed OUT\n"); | DBG_FUNC("failed OUT\n"); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* Subroutine used to delete an operational queue. | * Subroutine used to delete an operational queue. | ||||
*/ | */ | ||||
int pqisrc_delete_op_queue(pqisrc_softstate_t *softs, | int | ||||
pqisrc_delete_op_queue(pqisrc_softstate_t *softs, | |||||
uint32_t q_id, boolean_t ibq) | uint32_t q_id, boolean_t ibq) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
/* Firmware doesn't support this now */ | /* Firmware doesn't support this now */ | ||||
#if 0 | #if 0 | ||||
gen_adm_req_iu_t admin_req; | gen_adm_req_iu_t admin_req; | ||||
gen_adm_resp_iu_t admin_resp; | gen_adm_resp_iu_t admin_resp; | ||||
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.req_type.create_op_iq.qid = q_id; | admin_req.req_type.create_op_iq.qid = q_id; | ||||
if (ibq) | if (ibq) | ||||
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; | ||||
} | } | ||||
/* | /* | ||||
* Function used to destroy the event queue. | * Function used to destroy the event queue. | ||||
*/ | */ | ||||
void pqisrc_destroy_event_queue(pqisrc_softstate_t *softs) | void | ||||
pqisrc_destroy_event_queue(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (softs->event_q.created == true) { | if (softs->event_q.created == true) { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
ret = pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); | ret = pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Delete Event Q %d\n", softs->event_q.q_id); | DBG_ERR("Failed to Delete Event Q %d\n", softs->event_q.q_id); | ||||
} | } | ||||
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); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* | /* | ||||
* Function used to destroy operational ib queues. | * Function used to destroy operational ib queues. | ||||
*/ | */ | ||||
void pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) | void | ||||
pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
ib_queue_t *op_ib_q = NULL; | ib_queue_t *op_ib_q = NULL; | ||||
int i; | int i; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
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]; | ||||
if (op_ib_q->created == true) { | if (op_ib_q->created == true) { | ||||
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) { | ||||
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 AIO IB Q %d\n",op_ib_q->q_id); | DBG_ERR("Failed to Delete AIO 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; | ||||
} | } | ||||
} | } | ||||
/* Free the memory */ | /* Free the memory */ | ||||
os_dma_mem_free(softs, &softs->op_ibq_dma_mem); | os_dma_mem_free(softs, &softs->op_ibq_dma_mem); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* | /* | ||||
* Function used to destroy operational ob queues. | * Function used to destroy operational ob queues. | ||||
*/ | */ | ||||
void pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) | void | ||||
pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
int i; | int i; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
for (i = 0; i < softs->num_op_obq; i++) { | for (i = 0; i < softs->num_op_obq; i++) { | ||||
ob_queue_t *op_ob_q = NULL; | ob_queue_t *op_ob_q = NULL; | ||||
Show All 10 Lines | pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) | ||||
/* Free the memory */ | /* Free the memory */ | ||||
os_dma_mem_free(softs, &softs->op_obq_dma_mem); | os_dma_mem_free(softs, &softs->op_obq_dma_mem); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
} | } | ||||
/* | /* | ||||
* Function used to destroy an admin queue. | * Function used to destroy an admin queue. | ||||
*/ | */ | ||||
int pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs) | int | ||||
pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
#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; | ||||
} | } | ||||
/* | /* | ||||
* Function used to change operational ib queue properties. | * Function used to change operational ib queue properties. | ||||
*/ | */ | ||||
int pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs, | int | ||||
pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs, | |||||
ib_queue_t *op_ib_q, uint32_t prop) | ib_queue_t *op_ib_q, uint32_t prop) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS;; | int ret = PQI_STATUS_SUCCESS; | ||||
gen_adm_req_iu_t admin_req; | gen_adm_req_iu_t admin_req; | ||||
gen_adm_resp_iu_t admin_resp; | gen_adm_resp_iu_t admin_resp; | ||||
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; | ||||
} | } | ||||
/* | /* | ||||
* Function used to create an operational ob queue. | * Function used to create an operational ob queue. | ||||
*/ | */ | ||||
int pqisrc_create_op_obq(pqisrc_softstate_t *softs, | int | ||||
pqisrc_create_op_obq(pqisrc_softstate_t *softs, | |||||
ob_queue_t *op_ob_q) | ob_queue_t *op_ob_q) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS;; | int ret = PQI_STATUS_SUCCESS; | ||||
gen_adm_req_iu_t admin_req; | gen_adm_req_iu_t admin_req; | ||||
gen_adm_resp_iu_t admin_resp; | gen_adm_resp_iu_t admin_resp; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
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)); | ||||
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; | ||||
admin_req.req_type.create_op_oq.num_elem = op_ob_q->num_elem; | admin_req.req_type.create_op_oq.num_elem = op_ob_q->num_elem; | ||||
admin_req.req_type.create_op_oq.elem_len = op_ob_q->elem_size / 16; | admin_req.req_type.create_op_oq.elem_len = op_ob_q->elem_size / 16; | ||||
DBG_INFO("admin_req.req_type.create_op_oq.qid : %x\n",admin_req.req_type.create_op_oq.qid); | DBG_INFO("admin_req.req_type.create_op_oq.qid : %x\n",admin_req.req_type.create_op_oq.qid); | ||||
DBG_INFO("admin_req.req_type.create_op_oq.intr_msg_num : %x\n", admin_req.req_type.create_op_oq.intr_msg_num ); | DBG_INFO("admin_req.req_type.create_op_oq.intr_msg_num : %x\n", admin_req.req_type.create_op_oq.intr_msg_num ); | ||||
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); | ||||
} else { | } else { | ||||
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); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* Function used to create an operational ib queue. | * Function used to create an operational ib queue. | ||||
*/ | */ | ||||
int pqisrc_create_op_ibq(pqisrc_softstate_t *softs, | int | ||||
pqisrc_create_op_ibq(pqisrc_softstate_t *softs, | |||||
ib_queue_t *op_ib_q) | ib_queue_t *op_ib_q) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS;; | int ret = PQI_STATUS_SUCCESS; | ||||
gen_adm_req_iu_t admin_req; | gen_adm_req_iu_t admin_req; | ||||
gen_adm_resp_iu_t admin_resp; | gen_adm_resp_iu_t admin_resp; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
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)); | ||||
admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_IQ; | admin_req.fn_code = PQI_FUNCTION_CREATE_OPERATIONAL_IQ; | ||||
admin_req.req_type.create_op_iq.qid = op_ib_q->q_id; | admin_req.req_type.create_op_iq.qid = op_ib_q->q_id; | ||||
admin_req.req_type.create_op_iq.elem_arr_addr = op_ib_q->array_dma_addr; | admin_req.req_type.create_op_iq.elem_arr_addr = op_ib_q->array_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.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; | ||||
} | } | ||||
/* | /* | ||||
* subroutine used to create an operational ib queue for AIO. | * subroutine used to create an operational ib queue for AIO. | ||||
*/ | */ | ||||
int pqisrc_create_op_aio_ibq(pqisrc_softstate_t *softs, | int | ||||
pqisrc_create_op_aio_ibq(pqisrc_softstate_t *softs, | |||||
ib_queue_t *op_aio_ib_q) | ib_queue_t *op_aio_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_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, | ||||
op_aio_ib_q, PQI_CHANGE_OP_IQ_PROP_ASSIGN_AIO); | op_aio_ib_q, PQI_CHANGE_OP_IQ_PROP_ASSIGN_AIO); | ||||
DBG_FUNC("OUT ret : %d\n", ret); | DBG_FUNC("OUT ret : %d\n", ret); | ||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* subroutine used to create an operational ib queue for RAID. | * subroutine used to create an operational ib queue for RAID. | ||||
*/ | */ | ||||
int pqisrc_create_op_raid_ibq(pqisrc_softstate_t *softs, | int | ||||
pqisrc_create_op_raid_ibq(pqisrc_softstate_t *softs, | |||||
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; | ||||
} | } | ||||
/* | /* | ||||
* Allocate and create an event queue to process supported events. | * Allocate and create an event queue to process supported events. | ||||
*/ | */ | ||||
int pqisrc_alloc_and_create_event_queue(pqisrc_softstate_t *softs) | int | ||||
pqisrc_alloc_and_create_event_queue(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
uint32_t alloc_size = 0; | uint32_t alloc_size = 0; | ||||
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; | ||||
#endif | #endif | ||||
alloc_size = num_elem * PQISRC_EVENT_Q_ELEM_SIZE; | alloc_size = num_elem * PQISRC_EVENT_Q_ELEM_SIZE; | ||||
event_q_pi_dma_start_offset = alloc_size; | event_q_pi_dma_start_offset = alloc_size; | ||||
event_q_pi_virt_start_offset = alloc_size; | event_q_pi_virt_start_offset = alloc_size; | ||||
Show All 10 Lines | if (ret) { | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* Set up the address */ | /* Set up the address */ | ||||
virt_addr = softs->event_q_dma_mem.virt_addr; | virt_addr = softs->event_q_dma_mem.virt_addr; | ||||
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); | ||||
event_q->q_id = PQI_OP_EVENT_QUEUE_ID; | event_q->q_id = PQI_OP_EVENT_QUEUE_ID; | ||||
event_q->num_elem = num_elem; | event_q->num_elem = num_elem; | ||||
event_q->elem_size = PQISRC_EVENT_Q_ELEM_SIZE; | event_q->elem_size = PQISRC_EVENT_Q_ELEM_SIZE; | ||||
event_q->pi_dma_addr = event_q_pi_dma_start_offset; | event_q->pi_dma_addr = event_q_pi_dma_start_offset; | ||||
event_q->pi_virt_addr = (uint32_t *)event_q_pi_virt_start_addr; | event_q->pi_virt_addr = (uint32_t *)event_q_pi_virt_start_addr; | ||||
event_q->intr_msg_num = 0; /* vector zero for event */ | event_q->intr_msg_num = 0; /* vector zero for event */ | ||||
ASSERT(!(event_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ASSERT(!(event_q->pi_dma_addr & PQI_ADDR_ALIGN_MASK_4)); | ||||
ret = pqisrc_create_op_obq(softs,event_q); | ret = pqisrc_create_op_obq(softs,event_q); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Create EventQ %d\n",event_q->q_id); | DBG_ERR("Failed to Create EventQ %d\n",event_q->q_id); | ||||
goto err_out_create; | goto err_out_create; | ||||
} | } | ||||
event_q->created = true; | event_q->created = true; | ||||
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: | ||||
DBG_FUNC("OUT failed %d\n", ret); | DBG_FUNC("OUT failed %d\n", ret); | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
} | } | ||||
/* | /* | ||||
* 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; | ||||
uint32_t alloc_size = 0; | uint32_t alloc_size = 0; | ||||
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; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
/* 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*/ | ||||
/* Allocate memory for IB queues */ | /* Allocate memory for IB queues */ | ||||
softs->op_ibq_dma_mem.tag = "op_ib_queue"; | softs->op_ibq_dma_mem.tag = "op_ib_queue"; | ||||
softs->op_ibq_dma_mem.size = alloc_size; | softs->op_ibq_dma_mem.size = alloc_size; | ||||
softs->op_ibq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; | softs->op_ibq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; | ||||
ret = os_dma_mem_alloc(softs, &softs->op_ibq_dma_mem); | ret = os_dma_mem_alloc(softs, &softs->op_ibq_dma_mem); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Allocate Operational IBQ memory ret : %d\n", | DBG_ERR("Failed to Allocate Operational IBQ memory ret : %d\n", | ||||
ret); | ret); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* Set up the address */ | /* Set up the address */ | ||||
virt_addr = softs->op_ibq_dma_mem.virt_addr; | virt_addr = softs->op_ibq_dma_mem.virt_addr; | ||||
dma_addr = softs->op_ibq_dma_mem.dma_addr; | dma_addr = softs->op_ibq_dma_mem.dma_addr; | ||||
ib_ci_dma_start_offset += dma_addr; | ib_ci_dma_start_offset += dma_addr; | ||||
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]; | ||||
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, "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){ | ||||
/* TODO: error handling */ | |||||
DBG_ERR("raid_ibqlock %d init failed\n", i); | DBG_ERR("raid_ibqlock %d init failed\n", i); | ||||
op_ib_q->lockcreated = false; | op_ib_q->lockcreated = false; | ||||
goto err_lock; | 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", | ||||
__func__, op_ib_q->q_id); | __func__, op_ib_q->q_id); | ||||
goto err_out_create; | goto err_out_create; | ||||
} | } | ||||
op_ib_q->created = true; | op_ib_q->created = true; | ||||
/* OP AIO IB Q */ | /* OP AIO IB Q */ | ||||
virt_addr += ibq_size; | virt_addr += ibq_size; | ||||
dma_addr += ibq_size; | dma_addr += ibq_size; | ||||
op_ib_q = &softs->op_aio_ib_q[i]; | op_ib_q = &softs->op_aio_ib_q[i]; | ||||
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){ | ||||
/* TODO: error handling */ | |||||
DBG_ERR("aio_ibqlock %d init failed\n", i); | DBG_ERR("aio_ibqlock %d init failed\n", i); | ||||
op_ib_q->lockcreated = false; | op_ib_q->lockcreated = false; | ||||
goto err_lock; | 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) + 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; | ||||
} | } | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_lock: | err_lock: | ||||
err_out_create: | err_out_create: | ||||
pqisrc_destroy_op_ib_queues(softs); | pqisrc_destroy_op_ib_queues(softs); | ||||
err_out: | err_out: | ||||
DBG_FUNC("OUT failed %d\n", ret); | DBG_FUNC("OUT failed %d\n", ret); | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
} | } | ||||
/* | /* | ||||
* 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; | ||||
uint32_t alloc_size = 0; | uint32_t alloc_size = 0; | ||||
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; | ||||
ob_queue_t *op_ob_q = NULL; | ob_queue_t *op_ob_q = NULL; | ||||
uint32_t num_op_obq = softs->num_op_obq; | uint32_t num_op_obq = softs->num_op_obq; | ||||
int i = 0; | int i = 0; | ||||
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*/ | ||||
/* Allocate memory for OB queues */ | /* Allocate memory for OB queues */ | ||||
softs->op_obq_dma_mem.tag = "op_ob_queue"; | softs->op_obq_dma_mem.tag = "op_ob_queue"; | ||||
softs->op_obq_dma_mem.size = alloc_size; | softs->op_obq_dma_mem.size = alloc_size; | ||||
softs->op_obq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; | softs->op_obq_dma_mem.align = PQI_OPQ_ELEM_ARRAY_ALIGN; | ||||
ret = os_dma_mem_alloc(softs, &softs->op_obq_dma_mem); | ret = os_dma_mem_alloc(softs, &softs->op_obq_dma_mem); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Allocate Operational OBQ memory ret : %d\n", | DBG_ERR("Failed to Allocate Operational OBQ memory ret : %d\n", | ||||
ret); | ret); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
/* Set up the address */ | /* Set up the address */ | ||||
virt_addr = softs->op_obq_dma_mem.virt_addr; | virt_addr = softs->op_obq_dma_mem.virt_addr; | ||||
dma_addr = softs->op_obq_dma_mem.dma_addr; | dma_addr = softs->op_obq_dma_mem.dma_addr; | ||||
ob_pi_dma_start_offset += dma_addr; | ob_pi_dma_start_offset += dma_addr; | ||||
ob_pi_virt_start_addr = virt_addr + ob_pi_virt_start_offset; | ob_pi_virt_start_addr = virt_addr + ob_pi_virt_start_offset; | ||||
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 + | ||||
(i * sizeof(uint32_t)); | (i * sizeof(uint32_t)); | ||||
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); | ||||
goto err_out_create; | goto err_out_create; | ||||
} | } | ||||
op_ob_q->created = true; | op_ob_q->created = true; | ||||
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: | ||||
DBG_FUNC("OUT failed %d\n", ret); | DBG_FUNC("OUT failed %d\n", ret); | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
} | } | ||||
/* | /* | ||||
* 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) | ||||
goto err_out; | goto err_out; | ||||
/* Create Operational OB queues */ | /* Create Operational OB queues */ | ||||
ret = pqisrc_alloc_and_create_ob_queues(softs); | ret = pqisrc_alloc_and_create_ob_queues(softs); | ||||
if (ret) | if (ret) | ||||
goto err_out_obq; | goto err_out_obq; | ||||
/* 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: | ||||
DBG_FUNC("OUT failed %d\n", ret); | DBG_FUNC("OUT failed %d\n", ret); | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
} | } |