Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/smartpqi/smartpqi_intr.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. | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
softs->num_cpus_online = mp_ncpus; | softs->num_cpus_online = mp_ncpus; | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return PQI_STATUS_SUCCESS; | return PQI_STATUS_SUCCESS; | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
int os_get_intr_config(pqisrc_softstate_t *softs) | int os_get_intr_config(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
int msi_count = 0; | int msi_count = pci_msix_count(dev); | ||||
int error = 0; | int error = BSD_SUCCESS; | ||||
int ret = PQI_STATUS_SUCCESS; | |||||
dev = softs->os_specific.pqi_dev; | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
msi_count = pci_msix_count(dev); | |||||
if (msi_count > softs->num_cpus_online) | if (msi_count > softs->num_cpus_online) | ||||
msi_count = softs->num_cpus_online; | msi_count = softs->num_cpus_online; | ||||
if (msi_count > PQI_MAX_MSIX) | if (msi_count > PQI_MAX_MSIX) | ||||
Context not available. | |||||
if(!softs->intr_type) { | if(!softs->intr_type) { | ||||
DBG_FUNC("OUT failed\n"); | DBG_FUNC("OUT failed\n"); | ||||
ret = PQI_STATUS_FAILURE; | error = bsd_error_to_pqi_error(BSD_FAILURE); | ||||
return ret; | return error; | ||||
} | } | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | |||||
error = bsd_error_to_pqi_error(error); | |||||
return error; | |||||
} | } | ||||
void os_eventtaskqueue_enqueue(pqisrc_softstate_t *sc) | void os_eventtaskqueue_enqueue(pqisrc_softstate_t *sc) | ||||
Context not available. | |||||
pqi_intr_ctx_t *intr_ctx = (pqi_intr_ctx_t *)arg; | pqi_intr_ctx_t *intr_ctx = (pqi_intr_ctx_t *)arg; | ||||
pqisrc_softstate_t *softs = device_get_softc(intr_ctx->pqi_dev); | pqisrc_softstate_t *softs = device_get_softc(intr_ctx->pqi_dev); | ||||
int oq_id = intr_ctx->oq_id; | int oq_id = intr_ctx->oq_id; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (!softs) | |||||
return; | |||||
pqisrc_process_response_queue(softs, oq_id); | pqisrc_process_response_queue(softs, oq_id); | ||||
pqisrc_process_event_intr_src(softs, oq_id - 1); | pqisrc_process_event_intr_src(softs, oq_id - 1); | ||||
Context not available. | |||||
int oq_id = intr_ctx->oq_id; | int oq_id = intr_ctx->oq_id; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (!softs) | |||||
return; | |||||
pqisrc_process_response_queue(softs, oq_id); | pqisrc_process_response_queue(softs, oq_id); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
Context not available. | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (!softs) | |||||
return; | |||||
pqisrc_process_event_intr_src(softs, oq_id); | pqisrc_process_event_intr_src(softs, oq_id); | ||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
Context not available. | |||||
*/ | */ | ||||
int register_legacy_intr(pqisrc_softstate_t *softs) | int register_legacy_intr(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int error = 0; | int error = BSD_SUCCESS; | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
dev = softs->os_specific.pqi_dev; | |||||
softs->os_specific.pqi_irq_rid[0] = 0; | softs->os_specific.pqi_irq_rid[0] = 0; | ||||
softs->os_specific.pqi_irq[0] = bus_alloc_resource_any(dev, \ | softs->os_specific.pqi_irq[0] = bus_alloc_resource_any(dev, \ | ||||
SYS_RES_IRQ, &softs->os_specific.pqi_irq_rid[0], | SYS_RES_IRQ, &softs->os_specific.pqi_irq_rid[0], | ||||
RF_ACTIVE | RF_SHAREABLE); | RF_ACTIVE | RF_SHAREABLE); | ||||
if (NULL == softs->os_specific.pqi_irq[0]) { | if (NULL == softs->os_specific.pqi_irq[0]) { | ||||
DBG_ERR("Failed to allocate resource for interrupt\n"); | DBG_ERR("Failed to allocate resource for interrupt\n"); | ||||
return PQI_STATUS_FAILURE; | return BSD_FAILURE; | ||||
} | } | ||||
if ((softs->os_specific.msi_ctx = os_mem_alloc(softs,sizeof(pqi_intr_ctx_t))) == NULL) { | if ((softs->os_specific.msi_ctx = os_mem_alloc(softs,sizeof(pqi_intr_ctx_t))) == NULL) { | ||||
DBG_ERR("Failed to allocate memory for msi_ctx\n"); | DBG_ERR("Failed to allocate memory for msi_ctx\n"); | ||||
return PQI_STATUS_FAILURE; | return BSD_FAILURE; | ||||
} | } | ||||
softs->os_specific.msi_ctx[0].pqi_dev = dev; | softs->os_specific.msi_ctx[0].pqi_dev = dev; | ||||
/* For Legacy suport oq_id should be one */ | |||||
softs->os_specific.msi_ctx[0].oq_id = 1; | softs->os_specific.msi_ctx[0].oq_id = 1; | ||||
error = bus_setup_intr(dev, softs->os_specific.pqi_irq[0], | error = bus_setup_intr(dev, softs->os_specific.pqi_irq[0], | ||||
INTR_TYPE_CAM | INTR_MPSAFE, \ | INTR_TYPE_CAM | INTR_MPSAFE, \ | ||||
NULL, shared_ithread_routine, | NULL, shared_ithread_routine, | ||||
&softs->os_specific.msi_ctx[0], | &softs->os_specific.msi_ctx[0], | ||||
&softs->os_specific.intrcookie[0]); | &softs->os_specific.intrcookie[0]); | ||||
if (error) { | if (error) { | ||||
DBG_ERR("Failed to setup legacy interrupt err = %d\n", error); | DBG_ERR("Failed to setup legacy interrupt err = %d\n", error); | ||||
Context not available. | |||||
} | } | ||||
/* | /* | ||||
* Registration of MSIx | * Registration of MSIx | ||||
*/ | */ | ||||
int register_msix_intr(pqisrc_softstate_t *softs) | int register_msix_intr(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int error = 0; | int error = BSD_SUCCESS; | ||||
int i = 0; | int i = 0; | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
dev = softs->os_specific.pqi_dev; | |||||
int msix_count = softs->intr_count; | int msix_count = softs->intr_count; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
softs->os_specific.msi_ctx = os_mem_alloc(softs, sizeof(pqi_intr_ctx_t) * msix_count); | softs->os_specific.msi_ctx = os_mem_alloc(softs, sizeof(pqi_intr_ctx_t) * msix_count); | ||||
if (!softs->os_specific.msi_ctx) { | |||||
DBG_ERR("Memory allocation failed\n"); | |||||
return BSD_FAILURE; | |||||
} | |||||
/*Add shared handler */ | /*Add shared handler */ | ||||
if (softs->share_opq_and_eventq) { | if (softs->share_opq_and_eventq) { | ||||
softs->os_specific.pqi_irq_rid[i] = i+1; | softs->os_specific.pqi_irq_rid[i] = i+1; | ||||
Context not available. | |||||
if (NULL == softs->os_specific.pqi_irq[i]) { | if (NULL == softs->os_specific.pqi_irq[i]) { | ||||
DBG_ERR("Failed to allocate \ | DBG_ERR("Failed to allocate \ | ||||
event interrupt resource\n"); | event interrupt resource\n"); | ||||
return PQI_STATUS_FAILURE; | return BSD_FAILURE; | ||||
} | } | ||||
softs->os_specific.msi_ctx[i].pqi_dev = dev; | softs->os_specific.msi_ctx[i].pqi_dev = dev; | ||||
softs->os_specific.msi_ctx[i].oq_id = i+1; | softs->os_specific.msi_ctx[i].oq_id = i+1; | ||||
error = bus_setup_intr(dev,softs->os_specific.pqi_irq[i], | error = bus_setup_intr(dev,softs->os_specific.pqi_irq[i], | ||||
INTR_TYPE_CAM | INTR_MPSAFE,\ | INTR_TYPE_CAM | INTR_MPSAFE,\ | ||||
NULL, | NULL, | ||||
Context not available. | |||||
&softs->os_specific.intrcookie[i]); | &softs->os_specific.intrcookie[i]); | ||||
if (error) { | if (error) { | ||||
DBG_ERR("Failed to setup interrupt for events r=%d\n", | DBG_ERR("Failed to setup interrupt for events r=%d\n", | ||||
error); | error); | ||||
return error; | return error; | ||||
} | } | ||||
Context not available. | |||||
&softs->os_specific.pqi_irq_rid[i], | &softs->os_specific.pqi_irq_rid[i], | ||||
RF_SHAREABLE | RF_ACTIVE); | RF_SHAREABLE | RF_ACTIVE); | ||||
if (NULL == softs->os_specific.pqi_irq[i]) { | if (NULL == softs->os_specific.pqi_irq[i]) { | ||||
DBG_ERR("ERR : Failed to allocate \ | DBG_ERR("Failed to allocate event interrupt resource\n"); | ||||
event interrupt resource\n"); | return BSD_FAILURE; | ||||
return PQI_STATUS_FAILURE; | |||||
} | } | ||||
softs->os_specific.msi_ctx[i].pqi_dev = dev; | softs->os_specific.msi_ctx[i].pqi_dev = dev; | ||||
softs->os_specific.msi_ctx[i].oq_id = i; | softs->os_specific.msi_ctx[i].oq_id = i; | ||||
error = bus_setup_intr(dev,softs->os_specific.pqi_irq[i], | error = bus_setup_intr(dev,softs->os_specific.pqi_irq[i], | ||||
INTR_TYPE_CAM | INTR_MPSAFE,\ | INTR_TYPE_CAM | INTR_MPSAFE,\ | ||||
Context not available. | |||||
if (NULL == softs->os_specific.pqi_irq[i]) { | if (NULL == softs->os_specific.pqi_irq[i]) { | ||||
DBG_ERR("Failed to allocate \ | DBG_ERR("Failed to allocate \ | ||||
msi/x interrupt resource\n"); | msi/x interrupt resource\n"); | ||||
return PQI_STATUS_FAILURE; | return BSD_FAILURE; | ||||
} | } | ||||
softs->os_specific.msi_ctx[i].pqi_dev = dev; | softs->os_specific.msi_ctx[i].pqi_dev = dev; | ||||
softs->os_specific.msi_ctx[i].oq_id = i; | softs->os_specific.msi_ctx[i].oq_id = i; | ||||
Context not available. | |||||
*/ | */ | ||||
int os_setup_intr(pqisrc_softstate_t *softs) | int os_setup_intr(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
int error = 0; | int bsd_error, pqi_error; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
if (softs->intr_type == INTR_TYPE_FIXED) { | if (softs->intr_type == INTR_TYPE_FIXED) { | ||||
error = register_legacy_intr(softs); | bsd_error = register_legacy_intr(softs); | ||||
} | } | ||||
else { | else { | ||||
error = register_msix_intr(softs); | bsd_error = register_msix_intr(softs); | ||||
} | |||||
if (error) { | |||||
DBG_FUNC("OUT failed error = %d\n", error); | |||||
return error; | |||||
} | } | ||||
DBG_FUNC("OUT error = %d\n", error); | if(bsd_error) | ||||
DBG_WARN("interrupt registration is failed, error = %d\n", bsd_error); | |||||
return error; | pqi_error = bsd_error_to_pqi_error(bsd_error); | ||||
DBG_FUNC("OUT\n"); | |||||
return pqi_error; | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
*/ | */ | ||||
void deregister_pqi_intx(pqisrc_softstate_t *softs) | void deregister_pqi_intx(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
dev = softs->os_specific.pqi_dev; | |||||
if (softs->os_specific.pqi_irq[0] != NULL) { | if (softs->os_specific.pqi_irq[0] != NULL) { | ||||
if (softs->os_specific.intr_registered[0]) { | if (softs->os_specific.intr_registered[0]) { | ||||
bus_teardown_intr(dev, softs->os_specific.pqi_irq[0], | bus_teardown_intr(dev, softs->os_specific.pqi_irq[0], | ||||
Context not available. | |||||
*/ | */ | ||||
void deregister_pqi_msix(pqisrc_softstate_t *softs) | void deregister_pqi_msix(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
dev = softs->os_specific.pqi_dev; | |||||
int msix_count = softs->intr_count; | int msix_count = softs->intr_count; | ||||
int i = 0; | int i = 0; | ||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
os_mem_free(softs, (char*)softs->os_specific.msi_ctx, sizeof(pqi_intr_ctx_t) * msix_count); | os_mem_free(softs, (char*)softs->os_specific.msi_ctx, sizeof(pqi_intr_ctx_t) * msix_count); | ||||
softs->os_specific.msi_ctx = NULL; | softs->os_specific.msi_ctx = NULL; | ||||
Context not available. | |||||
*/ | */ | ||||
int os_destroy_intr(pqisrc_softstate_t *softs) | int os_destroy_intr(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
dev = softs->os_specific.pqi_dev; | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
Context not available. | |||||
*/ | */ | ||||
void os_free_intr_config(pqisrc_softstate_t *softs) | void os_free_intr_config(pqisrc_softstate_t *softs) | ||||
{ | { | ||||
device_t dev; | device_t dev = softs->os_specific.pqi_dev; | ||||
dev = softs->os_specific.pqi_dev; | |||||
DBG_FUNC("IN\n"); | DBG_FUNC("IN\n"); | ||||
Context not available. |