Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/smartpqi/smartpqi_event.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. | |||||
pqisrc_rescan_devices(pqisrc_softstate_t *softs) | pqisrc_rescan_devices(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int ret; | int ret; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
os_sema_lock(&softs->scan_lock); | os_sema_lock(&softs->scan_lock); | ||||
ret = pqisrc_scan_devices(softs); | ret = pqisrc_scan_devices(softs); | ||||
os_sema_unlock(&softs->scan_lock); | os_sema_unlock(&softs->scan_lock); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
Context not available. | |||||
/* | /* | ||||
* Subroutine to acknowledge the events processed by the driver to the adapter. | * Subroutine to acknowledge the events processed by the driver to the adapter. | ||||
*/ | */ | ||||
static void | static void | ||||
pqisrc_acknowledge_event(pqisrc_softstate_t *softs, | pqisrc_acknowledge_event(pqisrc_softstate_t *softs, | ||||
struct pqi_event *event) | struct pqi_event *event) | ||||
{ | { | ||||
pqi_event_acknowledge_request_t request; | pqi_event_acknowledge_request_t request; | ||||
ib_queue_t *ib_q = &softs->op_raid_ib_q[0]; | ib_queue_t *ib_q = &softs->op_raid_ib_q[0]; | ||||
int tmo = PQISRC_EVENT_ACK_RESP_TIMEOUT; | int tmo = PQISRC_EVENT_ACK_RESP_TIMEOUT; | ||||
Context not available. | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
request.header.iu_type = PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT; | request.header.iu_type = PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT; | ||||
request.header.iu_length = (sizeof(pqi_event_acknowledge_request_t) - | request.header.iu_length = (sizeof(pqi_event_acknowledge_request_t) - | ||||
PQI_REQUEST_HEADER_LENGTH); | PQI_REQUEST_HEADER_LENGTH); | ||||
request.event_type = event->event_type; | request.event_type = event->event_type; | ||||
request.event_id = event->event_id; | request.event_id = event->event_id; | ||||
Context not available. | |||||
COND_WAIT(((ib_q->pi_local) == *(ib_q->ci_virt_addr)), tmo); | COND_WAIT(((ib_q->pi_local) == *(ib_q->ci_virt_addr)), tmo); | ||||
if (tmo <= 0) { | if (tmo <= 0) { | ||||
DBG_ERR("wait for event acknowledge timed out\n"); | DBG_ERR("wait for event acknowledge timed out\n"); | ||||
DBG_ERR("tmo : %d\n",tmo); | DBG_ERR("tmo : %d\n",tmo); | ||||
} | } | ||||
DBG_FUNC(" OUT\n"); | DBG_FUNC(" OUT\n"); | ||||
} | } | ||||
Context not available. | |||||
int i; | int i; | ||||
struct pqi_event *pending_event; | struct pqi_event *pending_event; | ||||
pqisrc_softstate_t *softs = (pqisrc_softstate_t*)arg1; | pqisrc_softstate_t *softs = (pqisrc_softstate_t*)arg1; | ||||
DBG_FUNC(" IN\n"); | DBG_FUNC(" IN\n"); | ||||
Context not available. | |||||
} | } | ||||
pending_event++; | pending_event++; | ||||
} | } | ||||
/* Rescan devices except for heartbeat event */ | /* Rescan devices except for heartbeat event */ | ||||
if ((pqisrc_rescan_devices(softs)) != PQI_STATUS_SUCCESS) { | if ((pqisrc_rescan_devices(softs)) != PQI_STATUS_SUCCESS) { | ||||
DBG_ERR(" Failed to Re-Scan devices\n "); | DBG_ERR(" Failed to Re-Scan devices\n "); | ||||
} | } | ||||
DBG_FUNC(" OUT\n"); | DBG_FUNC(" OUT\n"); | ||||
} | } | ||||
/* | /* | ||||
* Get event index from event type to validate the type of event. | * Get event index from event type to validate the type of event. | ||||
*/ | */ | ||||
static int | static int | ||||
pqisrc_event_type_to_event_index(unsigned event_type) | pqisrc_event_type_to_event_index(unsigned event_type) | ||||
{ | { | ||||
int index; | int index; | ||||
Context not available. | |||||
/* | /* | ||||
* Function used to process the events supported by the adapter. | * Function used to process the events supported by the adapter. | ||||
*/ | */ | ||||
int | int | ||||
pqisrc_process_event_intr_src(pqisrc_softstate_t *softs,int obq_id) | pqisrc_process_event_intr_src(pqisrc_softstate_t *softs,int obq_id) | ||||
{ | { | ||||
uint32_t obq_pi,obq_ci; | uint32_t obq_pi,obq_ci; | ||||
Context not available. | |||||
ob_queue_t *event_q; | ob_queue_t *event_q; | ||||
struct pqi_event *pending_event; | struct pqi_event *pending_event; | ||||
boolean_t need_delayed_work = false; | boolean_t need_delayed_work = false; | ||||
DBG_FUNC(" IN\n"); | DBG_FUNC(" IN\n"); | ||||
OS_ATOMIC64_INC(softs, num_intrs); | |||||
event_q = &softs->event_q; | event_q = &softs->event_q; | ||||
obq_ci = event_q->ci_local; | obq_ci = event_q->ci_local; | ||||
obq_pi = *(event_q->pi_virt_addr); | obq_pi = *(event_q->pi_virt_addr); | ||||
DBG_INFO("Initial Event_q ci : %d Event_q pi : %d\n", obq_ci, obq_pi); | DBG_INFO("Initial Event_q ci : %d Event_q pi : %d\n", obq_ci, obq_pi); | ||||
while(1) { | while(1) { | ||||
int event_index; | int event_index; | ||||
DBG_INFO("queue_id : %d ci : %d pi : %d\n",obq_id, obq_ci, obq_pi); | DBG_INFO("queue_id : %d ci : %d pi : %d\n",obq_id, obq_ci, obq_pi); | ||||
Context not available. | |||||
pending_event->additional_event_id = response.additional_event_id; | pending_event->additional_event_id = response.additional_event_id; | ||||
} | } | ||||
} | } | ||||
obq_ci = (obq_ci + 1) % event_q->num_elem; | obq_ci = (obq_ci + 1) % event_q->num_elem; | ||||
} | } | ||||
/* Update CI */ | /* Update CI */ | ||||
event_q->ci_local = obq_ci; | event_q->ci_local = obq_ci; | ||||
PCI_MEM_PUT32(softs, event_q->ci_register_abs, | PCI_MEM_PUT32(softs, event_q->ci_register_abs, | ||||
event_q->ci_register_offset, event_q->ci_local); | event_q->ci_register_offset, event_q->ci_local); | ||||
Context not available. | |||||
DBG_FUNC("OUT"); | DBG_FUNC("OUT"); | ||||
return PQI_STATUS_SUCCESS; | return PQI_STATUS_SUCCESS; | ||||
} | } | ||||
/* | /* | ||||
* Function used to send a general management request to adapter. | * Function used to send a general management request to adapter. | ||||
*/ | */ | ||||
int pqisrc_submit_management_req(pqisrc_softstate_t *softs, | int pqisrc_submit_management_req(pqisrc_softstate_t *softs, | ||||
pqi_event_config_request_t *request) | pqi_event_config_request_t *request) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
ib_queue_t *op_ib_q = &softs->op_raid_ib_q[0]; | ib_queue_t *op_ib_q = &softs->op_raid_ib_q[0]; | ||||
rcb_t *rcb = NULL; | rcb_t *rcb = NULL; | ||||
DBG_FUNC(" IN\n"); | DBG_FUNC(" IN\n"); | ||||
/* Get the tag */ | /* Get the tag */ | ||||
Context not available. | |||||
if (INVALID_ELEM == request->request_id) { | if (INVALID_ELEM == request->request_id) { | ||||
DBG_ERR("Tag not available\n"); | DBG_ERR("Tag not available\n"); | ||||
ret = PQI_STATUS_FAILURE; | ret = PQI_STATUS_FAILURE; | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
rcb = &softs->rcb[request->request_id]; | rcb = &softs->rcb[request->request_id]; | ||||
Context not available. | |||||
goto err_cmd; | goto err_cmd; | ||||
} | } | ||||
ret = pqisrc_wait_on_condition(softs, rcb); | ret = pqisrc_wait_on_condition(softs, rcb, PQISRC_CMD_TIMEOUT); | ||||
if (ret != PQI_STATUS_SUCCESS) { | if (ret != PQI_STATUS_SUCCESS) { | ||||
DBG_ERR("Management request timed out !!\n"); | DBG_ERR("Management request timed out !!\n"); | ||||
goto err_cmd; | goto err_cmd; | ||||
} | } | ||||
os_reset_rcb(rcb); | os_reset_rcb(rcb); | ||||
pqisrc_put_tag(&softs->taglist,request->request_id); | pqisrc_put_tag(&softs->taglist,request->request_id); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_cmd: | err_cmd: | ||||
os_reset_rcb(rcb); | os_reset_rcb(rcb); | ||||
pqisrc_put_tag(&softs->taglist,request->request_id); | pqisrc_put_tag(&softs->taglist,request->request_id); | ||||
err_out: | err_out: | ||||
DBG_FUNC(" failed OUT : %d\n", ret); | DBG_FUNC(" failed OUT : %d\n", ret); | ||||
Context not available. | |||||
/* | /* | ||||
* Build and send the general management request. | * Build and send the general management request. | ||||
*/ | */ | ||||
static int | static int | ||||
pqi_event_configure(pqisrc_softstate_t *softs , | pqi_event_configure(pqisrc_softstate_t *softs , | ||||
pqi_event_config_request_t *request, | pqi_event_config_request_t *request, | ||||
dma_mem_t *buff) | dma_mem_t *buff) | ||||
{ | { | ||||
int ret = PQI_STATUS_SUCCESS; | int ret = PQI_STATUS_SUCCESS; | ||||
DBG_FUNC(" IN\n"); | DBG_FUNC(" IN\n"); | ||||
request->header.comp_feature = 0x00; | request->header.comp_feature = 0x00; | ||||
request->header.iu_length = sizeof(pqi_event_config_request_t) - | request->header.iu_length = sizeof(pqi_event_config_request_t) - | ||||
PQI_REQUEST_HEADER_LENGTH; /* excluding IU header length */ | PQI_REQUEST_HEADER_LENGTH; /* excluding IU header length */ | ||||
/*Op OQ id where response to be delivered */ | /*Op OQ id where response to be delivered */ | ||||
request->response_queue_id = softs->op_ob_q[0].q_id; | request->response_queue_id = softs->op_ob_q[0].q_id; | ||||
request->buffer_length = buff->size; | request->buffer_length = buff->size; | ||||
Context not available. | |||||
request->sg_desc.length = buff->size; | request->sg_desc.length = buff->size; | ||||
request->sg_desc.zero = 0; | request->sg_desc.zero = 0; | ||||
request->sg_desc.type = SGL_DESCRIPTOR_CODE_LAST_ALTERNATIVE_SGL_SEGMENT; | request->sg_desc.type = SGL_DESCRIPTOR_CODE_LAST_ALTERNATIVE_SGL_SEGMENT; | ||||
/* submit management req IU*/ | /* submit management req IU*/ | ||||
ret = pqisrc_submit_management_req(softs,request); | ret = pqisrc_submit_management_req(softs,request); | ||||
if(ret) | if(ret) | ||||
goto err_out; | goto err_out; | ||||
DBG_FUNC(" OUT\n"); | DBG_FUNC(" OUT\n"); | ||||
return ret; | return ret; | ||||
err_out: | err_out: | ||||
DBG_FUNC("Failed OUT\n"); | DBG_FUNC("Failed OUT\n"); | ||||
return ret; | return ret; | ||||
Context not available. | |||||
{ | { | ||||
int ret,i ; | int ret,i ; | ||||
pqi_event_config_request_t request; | pqi_event_config_request_t request; | ||||
pqi_event_config_t *event_config_p ; | pqi_event_config_t *event_config_p ; | ||||
dma_mem_t buf_report_event ; | dma_mem_t buf_report_event ; | ||||
/*bytes to be allocaed for report event config data-in buffer */ | /*bytes to be allocaed for report event config data-in buffer */ | ||||
uint32_t alloc_size = sizeof(pqi_event_config_t) ; | uint32_t alloc_size = sizeof(pqi_event_config_t) ; | ||||
memset(&request, 0 , sizeof(request)); | memset(&request, 0 , sizeof(request)); | ||||
DBG_FUNC(" IN\n"); | DBG_FUNC(" IN\n"); | ||||
memset(&buf_report_event, 0, sizeof(struct dma_mem)); | memset(&buf_report_event, 0, sizeof(struct dma_mem)); | ||||
buf_report_event.tag = "pqi_report_event_buf" ; | buf_report_event.tag = "pqi_report_event_buf" ; | ||||
buf_report_event.size = alloc_size; | buf_report_event.size = alloc_size; | ||||
buf_report_event.align = PQISRC_DEFAULT_DMA_ALIGN; | buf_report_event.align = PQISRC_DEFAULT_DMA_ALIGN; | ||||
/* allocate memory */ | /* allocate memory */ | ||||
ret = os_dma_mem_alloc(softs, &buf_report_event); | ret = os_dma_mem_alloc(softs, &buf_report_event); | ||||
if (ret) { | if (ret) { | ||||
Context not available. | |||||
} | } | ||||
DBG_INFO("buf_report_event.dma_addr = %p \n",(void*)buf_report_event.dma_addr); | DBG_INFO("buf_report_event.dma_addr = %p \n",(void*)buf_report_event.dma_addr); | ||||
DBG_INFO("buf_report_event.virt_addr = %p \n",(void*)buf_report_event.virt_addr); | DBG_INFO("buf_report_event.virt_addr = %p \n",(void*)buf_report_event.virt_addr); | ||||
request.header.iu_type = PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG; | request.header.iu_type = PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG; | ||||
/* Event configuration */ | /* Event configuration */ | ||||
ret=pqi_event_configure(softs,&request,&buf_report_event); | ret=pqi_event_configure(softs,&request,&buf_report_event); | ||||
if(ret) | if(ret) | ||||
goto free_mem; | goto free_mem; | ||||
event_config_p = (pqi_event_config_t*)buf_report_event.virt_addr; | event_config_p = (pqi_event_config_t*)buf_report_event.virt_addr; | ||||
softs->event_config.num_event_descriptors = MIN(event_config_p->num_event_descriptors, | softs->event_config.num_event_descriptors = MIN(event_config_p->num_event_descriptors, | ||||
PQI_MAX_EVENT_DESCRIPTORS) ; | PQI_MAX_EVENT_DESCRIPTORS) ; | ||||
for (i=0; i < softs->event_config.num_event_descriptors ;i++){ | for (i=0; i < softs->event_config.num_event_descriptors ;i++){ | ||||
softs->event_config.descriptors[i].event_type = | softs->event_config.descriptors[i].event_type = | ||||
event_config_p->descriptors[i].event_type; | event_config_p->descriptors[i].event_type; | ||||
} | } | ||||
/* free the allocated memory*/ | /* free the allocated memory*/ | ||||
os_dma_mem_free(softs, &buf_report_event); | os_dma_mem_free(softs, &buf_report_event); | ||||
DBG_FUNC(" OUT\n"); | DBG_FUNC(" OUT\n"); | ||||
return ret; | return ret; | ||||
Context not available. | |||||
buf_set_event.tag = "pqi_set_event_buf"; | buf_set_event.tag = "pqi_set_event_buf"; | ||||
buf_set_event.size = alloc_size; | buf_set_event.size = alloc_size; | ||||
buf_set_event.align = PQISRC_DEFAULT_DMA_ALIGN; | buf_set_event.align = PQISRC_DEFAULT_DMA_ALIGN; | ||||
/* allocate memory */ | /* allocate memory */ | ||||
ret = os_dma_mem_alloc(softs, &buf_set_event); | ret = os_dma_mem_alloc(softs, &buf_set_event); | ||||
if (ret) { | if (ret) { | ||||
DBG_ERR("Failed to Allocate set event config buffer : %d\n", ret); | DBG_ERR("Failed to Allocate set event config buffer : %d\n", ret); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
DBG_INFO("buf_set_event.dma_addr = %p\n",(void*)buf_set_event.dma_addr); | DBG_INFO("buf_set_event.dma_addr = %p\n",(void*)buf_set_event.dma_addr); | ||||
DBG_INFO("buf_set_event.virt_addr = %p\n",(void*)buf_set_event.virt_addr); | DBG_INFO("buf_set_event.virt_addr = %p\n",(void*)buf_set_event.virt_addr); | ||||
request.header.iu_type = PQI_REQUEST_IU_SET_EVENT_CONFIG; | request.header.iu_type = PQI_REQUEST_IU_SET_EVENT_CONFIG; | ||||
request.iu_specific.global_event_oq_id = softs->event_q.q_id; | request.iu_specific.global_event_oq_id = softs->event_q.q_id; | ||||
/*pointer to data-out buffer*/ | /*pointer to data-out buffer*/ | ||||
Context not available. | |||||
event_config_p->num_event_descriptors = softs->event_config.num_event_descriptors; | event_config_p->num_event_descriptors = softs->event_config.num_event_descriptors; | ||||
for (i=0; i < softs->event_config.num_event_descriptors ; i++){ | for (i=0; i < softs->event_config.num_event_descriptors ; i++){ | ||||
event_config_p->descriptors[i].event_type = | event_config_p->descriptors[i].event_type = | ||||
softs->event_config.descriptors[i].event_type; | softs->event_config.descriptors[i].event_type; | ||||
if( pqisrc_event_type_to_event_index(event_config_p->descriptors[i].event_type) != -1) | if( pqisrc_event_type_to_event_index(event_config_p->descriptors[i].event_type) != -1) | ||||
event_config_p->descriptors[i].oq_id = softs->event_q.q_id; | event_config_p->descriptors[i].oq_id = softs->event_q.q_id; | ||||
else | else | ||||
event_config_p->descriptors[i].oq_id = 0; /* Not supported this event. */ | event_config_p->descriptors[i].oq_id = 0; /* Not supported this event. */ | ||||
} | } | ||||
/* Event configuration */ | /* Event configuration */ | ||||
ret = pqi_event_configure(softs,&request,&buf_set_event); | ret = pqi_event_configure(softs,&request,&buf_set_event); | ||||
if(ret) | if(ret) | ||||
goto free_mem; | goto free_mem; | ||||
os_dma_mem_free(softs, &buf_set_event); | os_dma_mem_free(softs, &buf_set_event); | ||||
DBG_FUNC(" OUT\n"); | DBG_FUNC(" OUT\n"); | ||||
return ret; | return ret; | ||||
free_mem: | free_mem: | ||||
os_dma_mem_free(softs, &buf_set_event); | os_dma_mem_free(softs, &buf_set_event); | ||||
err_out: | err_out: | ||||
Context not available. |