blob: 675a0f926cea475ff8eb5db26f8df0c4abe5061b [file] [log] [blame]
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/debugfs.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include "edma.h"
#include "edma_regs.h"
#include "edma_debug.h"
/*
* edma_misc_stats_alloc()
* API to allocate memory for per-CPU miscellaneous stats
*/
int32_t edma_misc_stats_alloc()
{
uint32_t i;
edma_gbl_ctx.misc_stats = alloc_percpu(struct edma_misc_stats);
if (!edma_gbl_ctx.misc_stats) {
edma_err("Unable to allocate miscellaneous percpu stats\n");
return -ENOMEM;
}
for_each_possible_cpu(i) {
struct edma_misc_stats *stats;
stats = per_cpu_ptr(edma_gbl_ctx.misc_stats, i);
u64_stats_init(&stats->syncp);
}
return 0;
}
/*
* edma_misc_stats_free()
* API to free memory of per-CPU miscellaneous stats
*/
void edma_misc_stats_free()
{
if (edma_gbl_ctx.misc_stats) {
free_percpu(edma_gbl_ctx.misc_stats);
edma_gbl_ctx.misc_stats = NULL;
}
}
/*
* edma_misc_handle_irq()
* Process miscellaneous interrupts from EDMA
*/
irqreturn_t edma_misc_handle_irq(int irq, void *ctx)
{
uint32_t misc_intr_status, reg_data;
struct edma_gbl_ctx *egc = &edma_gbl_ctx;
struct edma_misc_stats *stats = this_cpu_ptr(edma_gbl_ctx.misc_stats);
/*
* Read Misc intr status
*/
reg_data = edma_reg_read(EDMA_REG_MISC_INT_STAT);
misc_intr_status = reg_data & egc->misc_intr_mask;
edma_debug("Received misc irq %d, status: %d\n", irq, misc_intr_status);
if (EDMA_MISC_AXI_RD_ERR_STATUS_GET(misc_intr_status)) {
edma_err("MISC AXI read error received\n");
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_axi_read_err;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_AXI_WR_ERR_STATUS_GET(misc_intr_status)) {
edma_err("MISC AXI write error received\n");
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_axi_write_err;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_RX_DESC_FIFO_FULL_STATUS_GET(misc_intr_status)) {
if (net_ratelimit()) {
edma_err("MISC Rx descriptor fifo full error received\n");
}
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_rx_desc_fifo_full;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_RX_ERR_BUF_SIZE_STATUS_GET(misc_intr_status)) {
if (net_ratelimit()) {
edma_err("MISC Rx buffer size error received\n");
}
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_rx_buf_size_err;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_TX_SRAM_FULL_STATUS_GET(misc_intr_status)) {
if (net_ratelimit()) {
edma_err("MISC Tx SRAM full error received\n");
}
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_tx_sram_full;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_TX_CMPL_BUF_FULL_STATUS_GET(misc_intr_status)) {
if (net_ratelimit()) {
edma_err("MISC Tx complete buffer full error received\n");
}
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_tx_cmpl_buf_full;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_DATA_LEN_ERR_STATUS_GET(misc_intr_status)) {
if (net_ratelimit()) {
edma_err("MISC data length error received\n");
}
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_tx_data_len_err;
u64_stats_update_end(&stats->syncp);
}
if (EDMA_MISC_TX_TIMEOUT_STATUS_GET(misc_intr_status)) {
if (net_ratelimit()) {
edma_err("MISC Tx timeout error received\n");
}
u64_stats_update_begin(&stats->syncp);
++stats->edma_misc_tx_timeout;
u64_stats_update_end(&stats->syncp);
}
return IRQ_HANDLED;
}